/* This should be made into an inline function in gmp.h. */ void _gcry_mpih_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) { int secure; if( up == vp ) { if( size < KARATSUBA_THRESHOLD ) _gcry_mpih_sqr_n_basecase( prodp, up, size ); else { mpi_ptr_t tspace; secure = _gcry_is_secure( up ); tspace = mpi_alloc_limb_space( 2 * size, secure ); _gcry_mpih_sqr_n( prodp, up, size, tspace ); _gcry_mpi_free_limb_space (tspace, 2 * size ); } } else { if( size < KARATSUBA_THRESHOLD ) mul_n_basecase( prodp, up, vp, size ); else { mpi_ptr_t tspace; secure = _gcry_is_secure( up ) || _gcry_is_secure( vp ); tspace = mpi_alloc_limb_space( 2 * size, secure ); mul_n (prodp, up, vp, size, tspace); _gcry_mpi_free_limb_space (tspace, 2 * size ); } } }
/**************** * Note: This copy function should not interpret the MPI * but copy it transparently. */ gcry_mpi_t _gcry_mpi_copy (gcry_mpi_t a) { int i; gcry_mpi_t b; if( a && (a->flags & 4) ) { void *p = _gcry_is_secure(a->d)? xmalloc_secure ((a->sign+7)/8) : xmalloc ((a->sign+7)/8); memcpy( p, a->d, (a->sign+7)/8 ); b = mpi_set_opaque( NULL, p, a->sign ); b->flags &= ~(16|32); /* Reset the immutable and constant flags. */ } else if( a ) { b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) : mpi_alloc( a->nlimbs ); b->nlimbs = a->nlimbs; b->sign = a->sign; b->flags = a->flags; b->flags &= ~(16|32); /* Reset the immutable and constant flags. */ for(i=0; i < b->nlimbs; i++ ) b->d[i] = a->d[i]; } else b = NULL; return b; }
gcry_mpi_t _gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits) { if (!a) a = mpi_alloc(0); if (mpi_is_immutable (a)) { mpi_immutable_failed (); return a; } if( a->flags & 4 ) xfree (a->d); else _gcry_mpi_free_limb_space (a->d, a->alloced); a->d = p; a->alloced = 0; a->nlimbs = 0; a->sign = nbits; a->flags = 4 | (a->flags & (GCRYMPI_FLAG_USER1|GCRYMPI_FLAG_USER2 |GCRYMPI_FLAG_USER3|GCRYMPI_FLAG_USER4)); if (_gcry_is_secure (a->d)) a->flags |= 1; return a; }
gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits) { void *d; unsigned int n; n = (nbits+7)/8; d = _gcry_is_secure (p)? xtrymalloc_secure (n) : xtrymalloc (n); if (!d) return NULL; memcpy (d, p, n); return mpi_set_opaque (a, d, nbits); }
void * _gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits) { const void *s; void *d; unsigned int n; s = mpi_get_opaque (a, nbits); if (!s && nbits) return NULL; n = (*nbits+7)/8; d = _gcry_is_secure (s)? xtrymalloc_secure (n) : xtrymalloc (n); if (d) memcpy (d, s, n); return d; }
/**************** * This function allocates an MPI which is optimized to hold * a value as large as the one given in the argument and allocates it * with the same flags as A. */ gcry_mpi_t _gcry_mpi_alloc_like( gcry_mpi_t a ) { gcry_mpi_t b; if( a && (a->flags & 4) ) { int n = (a->sign+7)/8; void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n) : xtrymalloc (n); memcpy( p, a->d, n ); b = mpi_set_opaque( NULL, p, a->sign ); } else if( a ) { b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) : mpi_alloc( a->nlimbs ); b->nlimbs = 0; b->sign = 0; b->flags = a->flags; } else b = NULL; return b; }
int gcry_is_secure (const void *a) { return _gcry_is_secure (a); }
void _gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, mpi_ptr_t vp, mpi_size_t vsize, struct karatsuba_ctx *ctx ) { mpi_limb_t cy; if( !ctx->tspace || ctx->tspace_size < vsize ) { if( ctx->tspace ) _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); ctx->tspace_nlimbs = 2 * vsize; ctx->tspace = mpi_alloc_limb_space (2 * vsize, (_gcry_is_secure (up) || _gcry_is_secure (vp))); ctx->tspace_size = vsize; } MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); prodp += vsize; up += vsize; usize -= vsize; if( usize >= vsize ) { if( !ctx->tp || ctx->tp_size < vsize ) { if( ctx->tp ) _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); ctx->tp_nlimbs = 2 * vsize; ctx->tp = mpi_alloc_limb_space (2 * vsize, (_gcry_is_secure (up) || _gcry_is_secure (vp))); ctx->tp_size = vsize; } do { MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); cy = _gcry_mpih_add_n( prodp, prodp, ctx->tp, vsize ); _gcry_mpih_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); prodp += vsize; up += vsize; usize -= vsize; } while( usize >= vsize ); } if( usize ) { if( usize < KARATSUBA_THRESHOLD ) { _gcry_mpih_mul( ctx->tspace, vp, vsize, up, usize ); } else { if( !ctx->next ) { ctx->next = xcalloc( 1, sizeof *ctx ); } _gcry_mpih_mul_karatsuba_case( ctx->tspace, vp, vsize, up, usize, ctx->next ); } cy = _gcry_mpih_add_n( prodp, prodp, ctx->tspace, vsize); _gcry_mpih_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); } }