diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c index 33bbebe3..891a7e65 100644 --- a/mpi/mpi-pow.c +++ b/mpi/mpi-pow.c @@ -1,324 +1,324 @@ /* mpi-pow.c - MPI functions for exponentiation * Copyright (C) 1994, 1996, 1998, 2000, 2002 * 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * * Note: This code is heavily based on the GNU MP Library. * Actually it's the same code with only minor changes in the * way the data is stored; this is to support the abstraction * of an optional secure memory allocation which may be used * to avoid revealing of sensitive data due to paging etc. */ #include #include #include #include #include "mpi-internal.h" #include "longlong.h" /**************** * RES = BASE ^ EXPO mod MOD */ void gcry_mpi_powm (gcry_mpi_t res, gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod) { /* Pointer to the limbs of the arguments, their size and signs. */ mpi_ptr_t rp, ep, mp, bp; mpi_size_t esize, msize, bsize, rsize; int msign, bsign, rsign; /* Flags telling the secure allocation status of the arguments. */ int esec, msec, bsec; /* Size of the result including space for temporary values. */ mpi_size_t size; /* Helper. */ int mod_shift_cnt; int negative_result; mpi_ptr_t mp_marker = NULL; mpi_ptr_t bp_marker = NULL; mpi_ptr_t ep_marker = NULL; mpi_ptr_t xp_marker = NULL; unsigned int mp_nlimbs = 0; unsigned int bp_nlimbs = 0; unsigned int ep_nlimbs = 0; unsigned int xp_nlimbs = 0; mpi_ptr_t tspace = NULL; mpi_size_t tsize = 0; esize = expo->nlimbs; msize = mod->nlimbs; size = 2 * msize; msign = mod->sign; esec = mpi_is_secure(expo); msec = mpi_is_secure(mod); bsec = mpi_is_secure(base); rp = res->d; ep = expo->d; if (!msize) - msize = 1 / msize; /* Provoke a signal. */ + _gcry_divide_by_zero(); if (!esize) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending on if MOD equals 1. */ rp[0] = 1; res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; res->sign = 0; goto leave; } /* Normalize MOD (i.e. make its most significant bit set) as required by mpn_divrem. This will make the intermediate values in the calculation slightly larger, but the correct result is obtained after a final reduction using the original MOD value. */ mp_nlimbs = msec? msize:0; mp = mp_marker = mpi_alloc_limb_space(msize, msec); count_leading_zeros (mod_shift_cnt, mod->d[msize-1]); if (mod_shift_cnt) _gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt); else MPN_COPY( mp, mod->d, msize ); bsize = base->nlimbs; bsign = base->sign; if (bsize > msize) { /* The base is larger than the module. Reduce it. Allocate (BSIZE + 1) with space for remainder and quotient. (The quotient is (bsize - msize + 1) limbs.) */ bp_nlimbs = bsec ? (bsize + 1):0; bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); MPN_COPY ( bp, base->d, bsize ); /* We don't care about the quotient, store it above the * remainder, at BP + MSIZE. */ _gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize ); bsize = msize; /* Canonicalize the base, since we are going to multiply with it quite a few times. */ MPN_NORMALIZE( bp, bsize ); } else bp = base->d; if (!bsize) { res->nlimbs = 0; res->sign = 0; goto leave; } /* Make BASE, EXPO and MOD not overlap with RES. */ if ( rp == bp ) { /* RES and BASE are identical. Allocate temp. space for BASE. */ gcry_assert (!bp_marker); bp_nlimbs = bsec? bsize:0; bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); MPN_COPY(bp, rp, bsize); } if ( rp == ep ) { /* RES and EXPO are identical. Allocate temp. space for EXPO. */ ep_nlimbs = esec? esize:0; ep = ep_marker = mpi_alloc_limb_space( esize, esec ); MPN_COPY(ep, rp, esize); } if ( rp == mp ) { /* RES and MOD are identical. Allocate temporary space for MOD.*/ gcry_assert (!mp_marker); mp_nlimbs = msec?msize:0; mp = mp_marker = mpi_alloc_limb_space( msize, msec ); MPN_COPY(mp, rp, msize); } /* Copy base to the result. */ if (res->alloced < size) { mpi_resize (res, size); rp = res->d; } MPN_COPY ( rp, bp, bsize ); rsize = bsize; rsign = bsign; /* Main processing. */ { mpi_size_t i; mpi_ptr_t xp; int c; mpi_limb_t e; mpi_limb_t carry_limb; struct karatsuba_ctx karactx; xp_nlimbs = msec? (2 * (msize + 1)):0; xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); memset( &karactx, 0, sizeof karactx ); negative_result = (ep[0] & 1) && base->sign; i = esize - 1; e = ep[i]; count_leading_zeros (c, e); e = (e << c) << 1; /* Shift the expo bits to the left, lose msb. */ c = BITS_PER_MPI_LIMB - 1 - c; /* Main loop. Make the result be pointed to alternately by XP and RP. This helps us avoid block copying, which would otherwise be necessary with the overlap restrictions of _gcry_mpih_divmod. With 50% probability the result after this loop will be in the area originally pointed by RP (==RES->d), and with 50% probability in the area originally pointed to by XP. */ for (;;) { while (c) { mpi_ptr_t tp; mpi_size_t xsize; /*mpih_mul_n(xp, rp, rp, rsize);*/ if ( rsize < KARATSUBA_THRESHOLD ) _gcry_mpih_sqr_n_basecase( xp, rp, rsize ); else { if ( !tspace ) { tsize = 2 * rsize; tspace = mpi_alloc_limb_space( tsize, 0 ); } else if ( tsize < (2*rsize) ) { _gcry_mpi_free_limb_space (tspace, 0); tsize = 2 * rsize; tspace = mpi_alloc_limb_space (tsize, 0 ); } _gcry_mpih_sqr_n (xp, rp, rsize, tspace); } xsize = 2 * rsize; if ( xsize > msize ) { _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); xsize = msize; } tp = rp; rp = xp; xp = tp; rsize = xsize; if ( (mpi_limb_signed_t)e < 0 ) { /*mpih_mul( xp, rp, rsize, bp, bsize );*/ if( bsize < KARATSUBA_THRESHOLD ) _gcry_mpih_mul ( xp, rp, rsize, bp, bsize ); else _gcry_mpih_mul_karatsuba_case (xp, rp, rsize, bp, bsize, &karactx); xsize = rsize + bsize; if ( xsize > msize ) { _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); xsize = msize; } tp = rp; rp = xp; xp = tp; rsize = xsize; } e <<= 1; c--; } i--; if ( i < 0 ) break; e = ep[i]; c = BITS_PER_MPI_LIMB; } /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT steps. Adjust the result by reducing it with the original MOD. Also make sure the result is put in RES->d (where it already might be, see above). */ if ( mod_shift_cnt ) { carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt); rp = res->d; if ( carry_limb ) { rp[rsize] = carry_limb; rsize++; } } else if (res->d != rp) { MPN_COPY (res->d, rp, rsize); rp = res->d; } if ( rsize >= msize ) { _gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize); rsize = msize; } /* Remove any leading zero words from the result. */ if ( mod_shift_cnt ) _gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt); MPN_NORMALIZE (rp, rsize); _gcry_mpih_release_karatsuba_ctx (&karactx ); } /* Fixup for negative results. */ if ( negative_result && rsize ) { if ( mod_shift_cnt ) _gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt); _gcry_mpih_sub( rp, mp, msize, rp, rsize); rsize = msize; rsign = msign; MPN_NORMALIZE(rp, rsize); } gcry_assert (res->d == rp); res->nlimbs = rsize; res->sign = rsign; leave: if (mp_marker) _gcry_mpi_free_limb_space( mp_marker, mp_nlimbs ); if (bp_marker) _gcry_mpi_free_limb_space( bp_marker, bp_nlimbs ); if (ep_marker) _gcry_mpi_free_limb_space( ep_marker, ep_nlimbs ); if (xp_marker) _gcry_mpi_free_limb_space( xp_marker, xp_nlimbs ); if (tspace) _gcry_mpi_free_limb_space( tspace, 0 ); } diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c index 224b8108..b33dcbfa 100644 --- a/mpi/mpih-div.c +++ b/mpi/mpih-div.c @@ -1,533 +1,532 @@ /* mpih-div.c - MPI helper functions * Copyright (C) 1994, 1996, 1998, 2000, * 2001, 2002 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * Note: This code is heavily based on the GNU MP Library. * Actually it's the same code with only minor changes in the * way the data is stored; this is to support the abstraction * of an optional secure memory allocation which may be used * to avoid revealing of sensitive data due to paging etc. */ #include #include #include #include "mpi-internal.h" #include "longlong.h" #ifndef UMUL_TIME #define UMUL_TIME 1 #endif #ifndef UDIV_TIME #define UDIV_TIME UMUL_TIME #endif /* FIXME: We should be using invert_limb (or invert_normalized_limb) * here (not udiv_qrnnd). */ mpi_limb_t _gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, mpi_limb_t divisor_limb) { mpi_size_t i; mpi_limb_t n1, n0, r; int dummy; /* Botch: Should this be handled at all? Rely on callers? */ if( !dividend_size ) return 0; /* If multiplication is much faster than division, and the * dividend is large, pre-invert the divisor, and use * only multiplications in the inner loop. * * This test should be read: * Does it ever help to use udiv_qrnnd_preinv? * && Does what we save compensate for the inversion overhead? */ if( UDIV_TIME > (2 * UMUL_TIME + 6) && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { int normalization_steps; count_leading_zeros( normalization_steps, divisor_limb ); if( normalization_steps ) { mpi_limb_t divisor_limb_inverted; divisor_limb <<= normalization_steps; /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the * most significant bit (with weight 2**N) implicit. * * Special case for DIVISOR_LIMB == 100...000. */ if( !(divisor_limb << 1) ) divisor_limb_inverted = ~(mpi_limb_t)0; else udiv_qrnnd(divisor_limb_inverted, dummy, -divisor_limb, 0, divisor_limb); n1 = dividend_ptr[dividend_size - 1]; r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); /* Possible optimization: * if (r == 0 * && divisor_limb > ((n1 << normalization_steps) * | (dividend_ptr[dividend_size - 2] >> ...))) * ...one division less... */ for( i = dividend_size - 2; i >= 0; i--) { n0 = dividend_ptr[i]; UDIV_QRNND_PREINV(dummy, r, r, ((n1 << normalization_steps) | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), divisor_limb, divisor_limb_inverted); n1 = n0; } UDIV_QRNND_PREINV(dummy, r, r, n1 << normalization_steps, divisor_limb, divisor_limb_inverted); return r >> normalization_steps; } else { mpi_limb_t divisor_limb_inverted; /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the * most significant bit (with weight 2**N) implicit. * * Special case for DIVISOR_LIMB == 100...000. */ if( !(divisor_limb << 1) ) divisor_limb_inverted = ~(mpi_limb_t)0; else udiv_qrnnd(divisor_limb_inverted, dummy, -divisor_limb, 0, divisor_limb); i = dividend_size - 1; r = dividend_ptr[i]; if( r >= divisor_limb ) r = 0; else i--; for( ; i >= 0; i--) { n0 = dividend_ptr[i]; UDIV_QRNND_PREINV(dummy, r, r, n0, divisor_limb, divisor_limb_inverted); } return r; } } else { if( UDIV_NEEDS_NORMALIZATION ) { int normalization_steps; count_leading_zeros(normalization_steps, divisor_limb); if( normalization_steps ) { divisor_limb <<= normalization_steps; n1 = dividend_ptr[dividend_size - 1]; r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); /* Possible optimization: * if (r == 0 * && divisor_limb > ((n1 << normalization_steps) * | (dividend_ptr[dividend_size - 2] >> ...))) * ...one division less... */ for(i = dividend_size - 2; i >= 0; i--) { n0 = dividend_ptr[i]; udiv_qrnnd (dummy, r, r, ((n1 << normalization_steps) | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), divisor_limb); n1 = n0; } udiv_qrnnd (dummy, r, r, n1 << normalization_steps, divisor_limb); return r >> normalization_steps; } } /* No normalization needed, either because udiv_qrnnd doesn't require * it, or because DIVISOR_LIMB is already normalized. */ i = dividend_size - 1; r = dividend_ptr[i]; if(r >= divisor_limb) r = 0; else i--; for(; i >= 0; i--) { n0 = dividend_ptr[i]; udiv_qrnnd (dummy, r, r, n0, divisor_limb); } return r; } } /* Divide num (NP/NSIZE) by den (DP/DSIZE) and write * the NSIZE-DSIZE least significant quotient limbs at QP * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is * non-zero, generate that many fraction bits and append them after the * other quotient limbs. * Return the most significant limb of the quotient, this is always 0 or 1. * * Preconditions: * 0. NSIZE >= DSIZE. * 1. The most significant bit of the divisor must be set. * 2. QP must either not overlap with the input operands at all, or * QP + DSIZE >= NP must hold true. (This means that it's * possible to put the quotient in the high part of NUM, right after the * remainder in NUM. * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. */ mpi_limb_t _gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, mpi_ptr_t np, mpi_size_t nsize, mpi_ptr_t dp, mpi_size_t dsize) { mpi_limb_t most_significant_q_limb = 0; switch(dsize) { case 0: - /* We are asked to divide by zero, so go ahead and do it! (To make - the compiler not remove this statement, return the value.) */ - return 1 / dsize; + _gcry_divide_by_zero(); + break; case 1: { mpi_size_t i; mpi_limb_t n1; mpi_limb_t d; d = dp[0]; n1 = np[nsize - 1]; if( n1 >= d ) { n1 -= d; most_significant_q_limb = 1; } qp += qextra_limbs; for( i = nsize - 2; i >= 0; i--) udiv_qrnnd( qp[i], n1, n1, np[i], d ); qp -= qextra_limbs; for( i = qextra_limbs - 1; i >= 0; i-- ) udiv_qrnnd (qp[i], n1, n1, 0, d); np[0] = n1; } break; case 2: { mpi_size_t i; mpi_limb_t n1, n0, n2; mpi_limb_t d1, d0; np += nsize - 2; d1 = dp[1]; d0 = dp[0]; n1 = np[1]; n0 = np[0]; if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { sub_ddmmss (n1, n0, n1, n0, d1, d0); most_significant_q_limb = 1; } for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { mpi_limb_t q; mpi_limb_t r; if( i >= qextra_limbs ) np--; else np[0] = 0; if( n1 == d1 ) { /* Q should be either 111..111 or 111..110. Need special * treatment of this rare case as normal division would * give overflow. */ q = ~(mpi_limb_t)0; r = n0 + d1; if( r < d1 ) { /* Carry in the addition? */ add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); qp[i] = q; continue; } n1 = d0 - (d0 != 0?1:0); n0 = -d0; } else { udiv_qrnnd (q, r, n1, n0, d1); umul_ppmm (n1, n0, d0, q); } n2 = np[0]; q_test: if( n1 > r || (n1 == r && n0 > n2) ) { /* The estimated Q was too large. */ q--; sub_ddmmss (n1, n0, n1, n0, 0, d0); r += d1; if( r >= d1 ) /* If not carry, test Q again. */ goto q_test; } qp[i] = q; sub_ddmmss (n1, n0, r, n2, n1, n0); } np[1] = n1; np[0] = n0; } break; default: { mpi_size_t i; mpi_limb_t dX, d1, n0; np += nsize - dsize; dX = dp[dsize - 1]; d1 = dp[dsize - 2]; n0 = np[dsize - 1]; if( n0 >= dX ) { if(n0 > dX || _gcry_mpih_cmp(np, dp, dsize - 1) >= 0 ) { _gcry_mpih_sub_n(np, np, dp, dsize); n0 = np[dsize - 1]; most_significant_q_limb = 1; } } for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { mpi_limb_t q; mpi_limb_t n1, n2; mpi_limb_t cy_limb; if( i >= qextra_limbs ) { np--; n2 = np[dsize]; } else { n2 = np[dsize - 1]; MPN_COPY_DECR (np + 1, np, dsize - 1); np[0] = 0; } if( n0 == dX ) { /* This might over-estimate q, but it's probably not worth * the extra code here to find out. */ q = ~(mpi_limb_t)0; } else { mpi_limb_t r; udiv_qrnnd(q, r, n0, np[dsize - 1], dX); umul_ppmm(n1, n0, d1, q); while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { q--; r += dX; if( r < dX ) /* I.e. "carry in previous addition?" */ break; n1 -= n0 < d1; n0 -= d1; } } /* Possible optimization: We already have (q * n0) and (1 * n1) * after the calculation of q. Taking advantage of that, we * could make this loop make two iterations less. */ cy_limb = _gcry_mpih_submul_1(np, dp, dsize, q); if( n2 != cy_limb ) { _gcry_mpih_add_n(np, np, dp, dsize); q--; } qp[i] = q; n0 = np[dsize - 1]; } } } return most_significant_q_limb; } /**************** * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. * Return the single-limb remainder. * There are no constraints on the value of the divisor. * * QUOT_PTR and DIVIDEND_PTR might point to the same limb. */ mpi_limb_t _gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, mpi_limb_t divisor_limb) { mpi_size_t i; mpi_limb_t n1, n0, r; int dummy; if( !dividend_size ) return 0; /* If multiplication is much faster than division, and the * dividend is large, pre-invert the divisor, and use * only multiplications in the inner loop. * * This test should be read: * Does it ever help to use udiv_qrnnd_preinv? * && Does what we save compensate for the inversion overhead? */ if( UDIV_TIME > (2 * UMUL_TIME + 6) && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { int normalization_steps; count_leading_zeros( normalization_steps, divisor_limb ); if( normalization_steps ) { mpi_limb_t divisor_limb_inverted; divisor_limb <<= normalization_steps; /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the * most significant bit (with weight 2**N) implicit. */ /* Special case for DIVISOR_LIMB == 100...000. */ if( !(divisor_limb << 1) ) divisor_limb_inverted = ~(mpi_limb_t)0; else udiv_qrnnd(divisor_limb_inverted, dummy, -divisor_limb, 0, divisor_limb); n1 = dividend_ptr[dividend_size - 1]; r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); /* Possible optimization: * if (r == 0 * && divisor_limb > ((n1 << normalization_steps) * | (dividend_ptr[dividend_size - 2] >> ...))) * ...one division less... */ for( i = dividend_size - 2; i >= 0; i--) { n0 = dividend_ptr[i]; UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, ((n1 << normalization_steps) | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), divisor_limb, divisor_limb_inverted); n1 = n0; } UDIV_QRNND_PREINV( quot_ptr[0], r, r, n1 << normalization_steps, divisor_limb, divisor_limb_inverted); return r >> normalization_steps; } else { mpi_limb_t divisor_limb_inverted; /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the * most significant bit (with weight 2**N) implicit. */ /* Special case for DIVISOR_LIMB == 100...000. */ if( !(divisor_limb << 1) ) divisor_limb_inverted = ~(mpi_limb_t) 0; else udiv_qrnnd(divisor_limb_inverted, dummy, -divisor_limb, 0, divisor_limb); i = dividend_size - 1; r = dividend_ptr[i]; if( r >= divisor_limb ) r = 0; else quot_ptr[i--] = 0; for( ; i >= 0; i-- ) { n0 = dividend_ptr[i]; UDIV_QRNND_PREINV( quot_ptr[i], r, r, n0, divisor_limb, divisor_limb_inverted); } return r; } } else { if(UDIV_NEEDS_NORMALIZATION) { int normalization_steps; count_leading_zeros (normalization_steps, divisor_limb); if( normalization_steps ) { divisor_limb <<= normalization_steps; n1 = dividend_ptr[dividend_size - 1]; r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); /* Possible optimization: * if (r == 0 * && divisor_limb > ((n1 << normalization_steps) * | (dividend_ptr[dividend_size - 2] >> ...))) * ...one division less... */ for( i = dividend_size - 2; i >= 0; i--) { n0 = dividend_ptr[i]; udiv_qrnnd (quot_ptr[i + 1], r, r, ((n1 << normalization_steps) | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), divisor_limb); n1 = n0; } udiv_qrnnd (quot_ptr[0], r, r, n1 << normalization_steps, divisor_limb); return r >> normalization_steps; } } /* No normalization needed, either because udiv_qrnnd doesn't require * it, or because DIVISOR_LIMB is already normalized. */ i = dividend_size - 1; r = dividend_ptr[i]; if(r >= divisor_limb) r = 0; else quot_ptr[i--] = 0; for(; i >= 0; i--) { n0 = dividend_ptr[i]; udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); } return r; } } diff --git a/src/g10lib.h b/src/g10lib.h index ec86c976..c580c085 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -1,367 +1,369 @@ /* g10lib.h - Internal definitions for libgcrypt * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 * 2007, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* This header is to be used inside of libgcrypt in place of gcrypt.h. This way we can better distinguish between internal and external usage of gcrypt.h. */ #ifndef G10LIB_H #define G10LIB_H 1 #ifdef _GCRYPT_H #error gcrypt.h already included #endif #ifndef _GCRYPT_IN_LIBGCRYPT #error something is wrong with config.h #endif #include #include #include "visibility.h" #include "types.h" /* Attribute handling macros. */ #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) #define JNLIB_GCC_M_FUNCTION 1 #define JNLIB_GCC_A_NR __attribute__ ((noreturn)) #define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) #define JNLIB_GCC_A_NR_PRINTF( f, a ) \ __attribute__ ((noreturn, format (printf,f,a))) #define GCC_ATTR_NORETURN __attribute__ ((__noreturn__)) #else #define JNLIB_GCC_A_NR #define JNLIB_GCC_A_PRINTF( f, a ) #define JNLIB_GCC_A_NR_PRINTF( f, a ) #define GCC_ATTR_NORETURN #endif #if __GNUC__ >= 3 /* According to glibc this attribute is available since 2.8 however we better play safe and use it only with gcc 3 or newer. */ #define GCC_ATTR_FORMAT_ARG(a) __attribute__ ((format_arg (a))) #else #define GCC_ATTR_FORMAT_ARG(a) #endif /* Gettext macros. */ #define _(a) _gcry_gettext(a) #define N_(a) (a) /* Some handy macros */ #ifndef STR #define STR(v) #v #endif #define STR2(v) STR(v) #define DIM(v) (sizeof(v)/sizeof((v)[0])) #define DIMof(type,member) DIM(((type *)0)->member) /*-- src/global.c -*/ int _gcry_global_is_operational (void); gcry_error_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr); void _gcry_check_heap (const void *a); int _gcry_get_debug_flag (unsigned int mask); /*-- src/misc.c --*/ #if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L void _gcry_bug (const char *file, int line, const char *func) GCC_ATTR_NORETURN; void _gcry_assert_failed (const char *expr, const char *file, int line, const char *func) GCC_ATTR_NORETURN; #else void _gcry_bug (const char *file, int line); void _gcry_assert_failed (const char *expr, const char *file, int line); #endif +void _gcry_divide_by_zero (void) JNLIB_GCC_A_NR; + const char *_gcry_gettext (const char *key) GCC_ATTR_FORMAT_ARG(1); void _gcry_fatal_error(int rc, const char *text ) JNLIB_GCC_A_NR; void _gcry_log( int level, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3); void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3); void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printhex (const char *text, const void *buffer, size_t length); void _gcry_set_log_verbosity( int level ); int _gcry_log_verbosity( int level ); #ifdef JNLIB_GCC_M_FUNCTION #define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ ) #define gcry_assert(expr) ((expr)? (void)0 \ : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __FUNCTION__)) #elif __STDC_VERSION__ >= 199901L #define BUG() _gcry_bug( __FILE__ , __LINE__, __func__ ) #define gcry_assert(expr) ((expr)? (void)0 \ : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __func__)) #else #define BUG() _gcry_bug( __FILE__ , __LINE__ ) #define gcry_assert(expr) ((expr)? (void)0 \ : _gcry_assert_failed (STR(expr), __FILE__, __LINE__)) #endif #define log_bug _gcry_log_bug #define log_fatal _gcry_log_fatal #define log_error _gcry_log_error #define log_info _gcry_log_info #define log_debug _gcry_log_debug #define log_printf _gcry_log_printf #define log_printhex _gcry_log_printhex /*-- src/hwfeatures.c --*/ /* (Do not change these values unless synced with the asm code.) */ #define HWF_PADLOCK_RNG 1 #define HWF_PADLOCK_AES 2 #define HWF_PADLOCK_SHA 4 #define HWF_PADLOCK_MMUL 8 #define HWF_INTEL_AESNI 256 unsigned int _gcry_get_hw_features (void); void _gcry_detect_hw_features (unsigned int); /*-- mpi/mpiutil.c --*/ const char *_gcry_mpi_get_hw_config (void); /*-- cipher/pubkey.c --*/ /* FIXME: shouldn't this go into mpi.h? */ #ifndef mpi_powm #define mpi_powm(w,b,e,m) gcry_mpi_powm( (w), (b), (e), (m) ) #endif /*-- primegen.c --*/ gcry_err_code_t _gcry_primegen_init (void); gcry_mpi_t _gcry_generate_secret_prime (unsigned int nbits, gcry_random_level_t random_level, int (*extra_check)(void*, gcry_mpi_t), void *extra_check_arg); gcry_mpi_t _gcry_generate_public_prime (unsigned int nbits, gcry_random_level_t random_level, int (*extra_check)(void*, gcry_mpi_t), void *extra_check_arg); gcry_mpi_t _gcry_generate_elg_prime (int mode, unsigned int pbits, unsigned int qbits, gcry_mpi_t g, gcry_mpi_t **factors); gcry_mpi_t _gcry_derive_x931_prime (const gcry_mpi_t xp, const gcry_mpi_t xp1, const gcry_mpi_t xp2, const gcry_mpi_t e, gcry_mpi_t *r_p1, gcry_mpi_t *r_p2); gpg_err_code_t _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, const void *seed, size_t seedlen, gcry_mpi_t *r_q, gcry_mpi_t *r_p, int *r_counter, void **r_seed, size_t *r_seedlen); gpg_err_code_t _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, const void *seed, size_t seedlen, gcry_mpi_t *r_q, gcry_mpi_t *r_p, int *r_counter, void **r_seed, size_t *r_seedlen, int *r_hashalgo); /* Replacements of missing functions (missing-string.c). */ #ifndef HAVE_STPCPY char *stpcpy (char *a, const char *b); #endif #ifndef HAVE_STRCASECMP int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE; #endif #include "../compat/libcompat.h" /* Macros used to rename missing functions. */ #ifndef HAVE_STRTOUL #define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) #endif #ifndef HAVE_MEMMOVE #define memmove(d, s, n) bcopy((s), (d), (n)) #endif #ifndef HAVE_STRICMP #define stricmp(a,b) strcasecmp( (a), (b) ) #endif #ifndef HAVE_ATEXIT #define atexit(a) (on_exit((a),0)) #endif #ifndef HAVE_RAISE #define raise(a) kill(getpid(), (a)) #endif /* Stack burning. */ void _gcry_burn_stack (int bytes); /* To avoid that a compiler optimizes certain memset calls away, these macros may be used instead. */ #define wipememory2(_ptr,_set,_len) do { \ volatile char *_vptr=(volatile char *)(_ptr); \ size_t _vlen=(_len); \ while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ } while(0) #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) /* Digit predicates. */ #define digitp(p) (*(p) >= '0' && *(p) <= '9') #define octdigitp(p) (*(p) >= '0' && *(p) <= '7') #define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \ || (*(a) >= 'a' && *(a) <= 'z')) #define hexdigitp(a) (digitp (a) \ || (*(a) >= 'A' && *(a) <= 'F') \ || (*(a) >= 'a' && *(a) <= 'f')) /* Management for ciphers/digests/pubkey-ciphers. */ /* Structure for each registered `module'. */ struct gcry_module { struct gcry_module *next; /* List pointers. */ struct gcry_module **prevp; void *spec; /* Pointer to the subsystem-specific specification structure. */ void *extraspec; /* Pointer to the subsystem-specific extra specification structure. */ int flags; /* Associated flags. */ int counter; /* Use counter. */ unsigned int mod_id; /* ID of this module. */ }; /* Flags for the `flags' member of gcry_module_t. */ #define FLAG_MODULE_DISABLED (1 << 0) gcry_err_code_t _gcry_module_add (gcry_module_t *entries, unsigned int id, void *spec, void *extraspec, gcry_module_t *module); typedef int (*gcry_module_lookup_t) (void *spec, void *data); /* Lookup a module specification by it's ID. After a successful lookup, the module has it's resource counter incremented. */ gcry_module_t _gcry_module_lookup_id (gcry_module_t entries, unsigned int id); /* Internal function. Lookup a module specification. */ gcry_module_t _gcry_module_lookup (gcry_module_t entries, void *data, gcry_module_lookup_t func); /* Release a module. In case the use-counter reaches zero, destroy the module. */ void _gcry_module_release (gcry_module_t entry); /* Add a reference to a module. */ void _gcry_module_use (gcry_module_t module); /* Return a list of module IDs. */ gcry_err_code_t _gcry_module_list (gcry_module_t modules, int *list, int *list_length); gcry_err_code_t _gcry_cipher_init (void); gcry_err_code_t _gcry_md_init (void); gcry_err_code_t _gcry_pk_init (void); gcry_err_code_t _gcry_secmem_module_init (void); gcry_err_code_t _gcry_pk_module_lookup (int id, gcry_module_t *module); void _gcry_pk_module_release (gcry_module_t module); gcry_err_code_t _gcry_pk_get_elements (int algo, char **enc, char **sig); /* Memory management. */ #define GCRY_ALLOC_FLAG_SECURE (1 << 0) /*-- sexp.c --*/ gcry_error_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, const char *format, va_list arg_ptr); char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number); /*-- fips.c --*/ void _gcry_initialize_fips_mode (int force); int _gcry_fips_mode (void); #define fips_mode() _gcry_fips_mode () int _gcry_enforced_fips_mode (void); void _gcry_set_enforced_fips_mode (void); void _gcry_inactivate_fips_mode (const char *text); int _gcry_is_fips_mode_inactive (void); void _gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc, int is_fatal, const char *description); #ifdef JNLIB_GCC_M_FUNCTION # define fips_signal_error(a) \ _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 0, (a)) # define fips_signal_fatal_error(a) \ _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 1, (a)) #else # define fips_signal_error(a) \ _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 0, (a)) # define fips_signal_fatal_error(a) \ _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a)) #endif int _gcry_fips_is_operational (void); #define fips_is_operational() (_gcry_global_is_operational ()) #define fips_not_operational() (GCRY_GPG_ERR_NOT_OPERATIONAL) int _gcry_fips_test_operational (void); int _gcry_fips_test_error_or_operational (void); gpg_err_code_t _gcry_fips_run_selftests (int extended); void _gcry_fips_noreturn (void); #define fips_noreturn() (_gcry_fips_noreturn ()) #endif /* G10LIB_H */ diff --git a/src/misc.c b/src/misc.c index 17bd5467..ed72ed63 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,298 +1,306 @@ /* misc.c * Copyright (C) 1999, 2001, 2002, 2003, 2007, * 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include +#include #include #include #include #include #include #include "g10lib.h" #include "secmem.h" static int verbosity_level = 0; static void (*fatal_error_handler)(void*,int, const char*) = NULL; static void *fatal_error_handler_value = 0; static void (*log_handler)(void*,int, const char*, va_list) = NULL; static void *log_handler_value = 0; static const char *(*user_gettext_handler)( const char * ) = NULL; void gcry_set_gettext_handler( const char *(*f)(const char*) ) { user_gettext_handler = f; } const char * _gcry_gettext( const char *key ) { if( user_gettext_handler ) return user_gettext_handler( key ); /* FIXME: switch the domain to gnupg and restore later */ return key; } void gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value) { fatal_error_handler_value = value; fatal_error_handler = fnc; } static void write2stderr( const char *s ) { /* Dummy variable to silence gcc warning. */ int res = write( 2, s, strlen(s) ); (void) res; } /* * This function is called for fatal errors. A caller might want to * set his own handler because this function simply calls abort(). */ void _gcry_fatal_error (int rc, const char *text) { if ( !text ) /* get a default text */ text = gpg_strerror (rc); if (fatal_error_handler && !fips_mode () ) fatal_error_handler (fatal_error_handler_value, rc, text); fips_signal_fatal_error (text); write2stderr("\nFatal error: "); write2stderr(text); write2stderr("\n"); _gcry_secmem_term (); abort (); } void gcry_set_log_handler( void (*f)(void*,int, const char*, va_list ), void *opaque ) { log_handler = f; log_handler_value = opaque; } void _gcry_set_log_verbosity( int level ) { verbosity_level = level; } int _gcry_log_verbosity( int level ) { return verbosity_level >= level; } /**************** * This is our log function which prints all log messages to stderr or * using the function defined with gcry_set_log_handler(). */ static void _gcry_logv( int level, const char *fmt, va_list arg_ptr ) { if (log_handler) log_handler (log_handler_value, level, fmt, arg_ptr); else { switch (level) { case GCRY_LOG_CONT: break; case GCRY_LOG_INFO: break; case GCRY_LOG_WARN: break; case GCRY_LOG_ERROR: break; case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break; case GCRY_LOG_BUG: fputs("Ohhhh jeeee: ", stderr); break; case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break; default: fprintf(stderr,"[Unknown log level %d]: ", level ); break; } vfprintf(stderr,fmt,arg_ptr) ; } if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG ) { fips_signal_fatal_error ("internal error (fatal or bug)"); _gcry_secmem_term (); abort (); } } void _gcry_log( int level, const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( level, fmt, arg_ptr ); va_end(arg_ptr); } #if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L void _gcry_bug( const char *file, int line, const char *func ) { _gcry_log( GCRY_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func ); abort(); /* never called, but it makes the compiler happy */ } void _gcry_assert_failed (const char *expr, const char *file, int line, const char *func) { _gcry_log (GCRY_LOG_BUG, ("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func ); abort(); /* Never called, but it makes the compiler happy. */ } #else void _gcry_bug( const char *file, int line ) { _gcry_log( GCRY_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line); abort(); /* never called, but it makes the compiler happy */ } void _gcry_assert_failed (const char *expr, const char *file, int line) { _gcry_log (GCRY_LOG_BUG, ("Assertion `%s' failed (%s:%d)\n"), expr, file, line); abort(); /* Never called, but it makes the compiler happy. */ } #endif void _gcry_log_info( const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr ); va_end(arg_ptr); } int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) { va_list arg_ptr; (void)fp; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr ); va_end(arg_ptr); return 0; } void _gcry_log_error( const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr ); va_end(arg_ptr); } void _gcry_log_fatal( const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr ); va_end(arg_ptr); abort(); /* never called, but it makes the compiler happy */ } void _gcry_log_bug( const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr ); va_end(arg_ptr); abort(); /* never called, but it makes the compiler happy */ } void _gcry_log_debug( const char *fmt, ... ) { va_list arg_ptr ; va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr ); va_end(arg_ptr); } void _gcry_log_printf (const char *fmt, ...) { va_list arg_ptr; if (fmt) { va_start( arg_ptr, fmt ) ; _gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr); va_end(arg_ptr); } } /* Print a hexdump of BUFFER. With TEXT of NULL print just the raw dump, with TEXT an empty string, print a trailing linefeed, otherwise print an entire debug line. */ void _gcry_log_printhex (const char *text, const void *buffer, size_t length) { if (text && *text) log_debug ("%s ", text); if (length) { const unsigned char *p = buffer; log_printf ("%02X", *p); for (length--, p++; length--; p++) log_printf (" %02X", *p); } if (text) log_printf ("\n"); } void _gcry_burn_stack (int bytes) { char buf[64]; wipememory (buf, sizeof buf); bytes -= sizeof buf; if (bytes > 0) _gcry_burn_stack (bytes); } + +void +_gcry_divide_by_zero (void) +{ + gpg_err_set_errno (EDOM); + _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero"); +}