mpi_alloc_like( MPI a ) #endif { MPI b; if( a && (a->flags & 4) ) { void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits ) : xmalloc( a->nbits ); memcpy( p, a->d, a->nbits ); b = mpi_set_opaque( NULL, p, a->nbits ); } else if( a ) { #ifdef M_DEBUG b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) : mpi_debug_alloc( a->nlimbs, info ); #else b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) : mpi_alloc( a->nlimbs ); #endif b->nlimbs = 0; b->sign = 0; b->flags = a->flags; b->nbits = 0; } else b = NULL; return b; }
/**************** * 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)? gcry_xmalloc_secure( (a->sign+7)/8 ) : gcry_xmalloc( (a->sign+7)/8 ); memcpy( p, a->d, (a->sign+7)/8 ); b = gcry_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 = a->nlimbs; b->sign = a->sign; b->flags = a->flags; for(i=0; i < b->nlimbs; i++ ) b->d[i] = a->d[i]; } else b = NULL; return b; }
/**************** * 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; }
mpi_copy_gpg( MPI a ) #endif { int i; MPI b; if( a && (a->flags & 4) ) { void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits ) : xmalloc( a->nbits ); memcpy( p, a->d, a->nbits ); b = mpi_set_opaque( NULL, p, a->nbits ); } else if( a ) { #ifdef M_DEBUG b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) : mpi_debug_alloc( a->nlimbs, info ); #else b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) : mpi_alloc( a->nlimbs ); #endif b->nlimbs = a->nlimbs; b->sign = a->sign; b->flags = a->flags; b->nbits = a->nbits; for(i=0; i < b->nlimbs; i++ ) b->d[i] = a->d[i]; } else b = NULL; return b; }
MPI mpi_read_from_buffer(byte *buffer, unsigned int *ret_nread, int secure) { int i, j; unsigned nbits, nbytes, nlimbs, nread=0; mpi_limb_t a; MPI val = NULL; if( *ret_nread < 2 ) goto leave; nbits = buffer[0] << 8 | buffer[1]; if( nbits > MAX_EXTERN_MPI_BITS ) { log_info ("mpi too large (%u bits)\n", nbits); goto leave; } buffer += 2; nread = 2; nbytes = (nbits+7) / 8; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; val = secure? mpi_alloc_secure( nlimbs ) : mpi_alloc( nlimbs ); i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; j= val->nlimbs = nlimbs; val->sign = 0; for( ; j > 0; j-- ) { a = 0; for(; i < BYTES_PER_MPI_LIMB; i++ ) { if( ++nread > *ret_nread ) { /* This (as well as the above error condition) may happen if we use this function to parse a decrypted MPI which didn't turn out to be a real MPI - possible because the supplied key was wrong but the OpenPGP checksum didn't caught it. */ log_info ("mpi larger than buffer\n"); mpi_free (val); val = NULL; goto leave; } a <<= 8; a |= *buffer++; } i = 0; val->d[j-1] = a; } leave: *ret_nread = nread; return val; }
mpi_read(IOBUF inp, unsigned *ret_nread, int secure) #endif { int c, i, j; unsigned nbits, nbytes, nlimbs, nread=0; mpi_limb_t a; MPI val = MPI_NULL; if( (c = iobuf_get(inp)) == -1 ) goto leave; nbits = c << 8; if( (c = iobuf_get(inp)) == -1 ) goto leave; nbits |= c; if( nbits > MAX_EXTERN_MPI_BITS ) { log_error("mpi too large (%u bits)\n", nbits); goto leave; } nread = 2; nbytes = (nbits+7) / 8; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; #ifdef M_DEBUG val = secure? mpi_debug_alloc_secure( nlimbs, info ) : mpi_debug_alloc( nlimbs, info ); #else val = secure? mpi_alloc_secure( nlimbs ) : mpi_alloc( nlimbs ); #endif i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; j= val->nlimbs = nlimbs; val->sign = 0; for( ; j > 0; j-- ) { a = 0; for(; i < BYTES_PER_MPI_LIMB; i++ ) { a <<= 8; a |= iobuf_get(inp) & 0xff; nread++; } i = 0; val->d[j-1] = a; } leave: if( nread > *ret_nread ) log_bug("mpi crosses packet border\n"); else *ret_nread = nread; return val; }
/* Helper used to scan PGP style MPIs. Returns NULL on failure. */ static gcry_mpi_t mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread, int secure) { int i, j; unsigned int nbits, nbytes, nlimbs, nread=0; mpi_limb_t a; gcry_mpi_t val = MPI_NULL; if ( *ret_nread < 2 ) goto leave; nbits = buffer[0] << 8 | buffer[1]; if ( nbits > MAX_EXTERN_MPI_BITS ) { /* log_debug ("mpi too large (%u bits)\n", nbits); */ goto leave; } buffer += 2; nread = 2; nbytes = (nbits+7) / 8; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs); i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; j= val->nlimbs = nlimbs; val->sign = 0; for ( ; j > 0; j-- ) { a = 0; for (; i < BYTES_PER_MPI_LIMB; i++ ) { if ( ++nread > *ret_nread ) { /* log_debug ("mpi larger than buffer"); */ mpi_free (val); val = NULL; goto leave; } a <<= 8; a |= *buffer++; } i = 0; val->d[j-1] = a; } leave: *ret_nread = nread; return val; }
int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) { ELG_secret_key sk; if( !is_ELGAMAL(algo) ) return G10ERR_PUBKEY_ALGO; if( !data[0] || !data[1] || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) return G10ERR_BAD_MPI; sk.p = skey[0]; sk.g = skey[1]; sk.y = skey[2]; sk.x = skey[3]; *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); decrypt( *result, data[0], data[1], &sk ); return 0; }
MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure) { int i, j; unsigned nbits, nbytes, nlimbs, nread=0; mpi_limb_t a; MPI val = MPI_NULL; if( *ret_nread < 2 ) goto leave; nbits = buffer[0] << 8 | buffer[1]; if( nbits > MAX_EXTERN_MPI_BITS ) { log_error("mpi too large (%u bits)\n", nbits); goto leave; } buffer += 2; nread = 2; nbytes = (nbits+7) / 8; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; val = secure? mpi_alloc_secure( nlimbs ) : mpi_alloc( nlimbs ); i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; j= val->nlimbs = nlimbs; val->sign = 0; for( ; j > 0; j-- ) { a = 0; for(; i < BYTES_PER_MPI_LIMB; i++ ) { if( ++nread > *ret_nread ) log_bug("mpi larger than buffer\n"); a <<= 8; a |= *buffer++; } i = 0; val->d[j-1] = a; } leave: *ret_nread = nread; return val; }
static void decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) { gcry_mpi_t t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); /* output = b/(a^x) mod p */ gcry_mpi_powm( t1, a, skey->x, skey->p ); mpi_invm( t1, t1, skey->p ); mpi_mulm( output, b, t1, skey->p ); #if 0 if( DBG_CIPHER ) { log_mpidump("elg decrypted x= ", skey->x); log_mpidump("elg decrypted p= ", skey->p); log_mpidump("elg decrypted a= ", a); log_mpidump("elg decrypted b= ", b); log_mpidump("elg decrypted M= ", output); } #endif mpi_free(t1); }
/**************** * 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; }
gcry_err_code_t _gcry_elg_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) { gcry_err_code_t err = GPG_ERR_NO_ERROR; ELG_secret_key sk; (void)algo; (void)flags; if ((! data[0]) || (! data[1]) || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) err = GPG_ERR_BAD_MPI; else { sk.p = skey[0]; sk.g = skey[1]; sk.y = skey[2]; sk.x = skey[3]; *result = mpi_alloc_secure (mpi_get_nlimbs (sk.p)); decrypt (*result, data[0], data[1], &sk); } return err; }
/**************** * Generate a key pair with a key of size NBITS * Returns: 2 structures filles with all needed values * and an array with n-1 factors of (p-1) */ static void generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors ) { MPI p; /* the prime */ MPI p_min1; MPI g; MPI x; /* the secret exponent */ MPI y; MPI temp; unsigned int qbits; unsigned int xbits; byte *rndbuf; p_min1 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); temp = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); qbits = wiener_map ( nbits ); if( qbits & 1 ) /* better have a even one */ qbits++; g = mpi_alloc(1); p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui(p_min1, p, 1); /* select a random number which has these properties: * 0 < x < p-1 * This must be a very good random number because this is the * secret part. The prime is public and may be shared anyway, * so a random generator level of 1 is used for the prime. * * I don't see a reason to have a x of about the same size as the * p. It should be sufficient to have one about the size of q or * the later used k plus a large safety margin. Decryption will be * much faster with such an x. Note that this is not optimal for * signing keys becuase it makes an attack using accidential small * K values even easier. Well, one should not use ElGamal signing * anyway. */ xbits = qbits * 3 / 2; if( xbits >= nbits ) BUG(); x = mpi_alloc_secure ( mpi_nlimb_hint_from_nbits (xbits) ); if( DBG_CIPHER ) log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; do { if( DBG_CIPHER ) progress('.'); if( rndbuf ) { /* change only some of the higher bits */ if( xbits < 16 ) {/* should never happen ... */ xfree(rndbuf); rndbuf = get_random_bits( xbits, 2, 1 ); } else { char *r = get_random_bits( 16, 2, 1 ); memcpy(rndbuf, r, 16/8 ); xfree(r); } } else rndbuf = get_random_bits( xbits, 2, 1 ); mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); mpi_clear_highbit( x, xbits+1 ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); xfree(rndbuf); y = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); mpi_powm( y, g, x, p ); if( DBG_CIPHER ) { progress('\n'); log_mpidump("elg p= ", p ); log_mpidump("elg g= ", g ); log_mpidump("elg y= ", y ); log_mpidump("elg x= ", x ); } /* copy the stuff to the key structures */ sk->p = p; sk->g = g; sk->y = y; sk->x = x; /* now we can test our keys (this should never fail!) */ test_keys( sk, nbits - 64 ); mpi_free( p_min1 ); mpi_free( temp ); }
static MPI gen_prime( unsigned nbits, int secret, int randomlevel ) { unsigned nlimbs; MPI prime, ptest, pminus1, val_2, val_3, result; int i; unsigned x, step; unsigned count1, count2; int *mods; if( 0 && DBG_CIPHER ) log_debug("generate a prime of %u bits ", nbits ); if( !no_of_small_prime_numbers ) { for(i=0; small_prime_numbers[i]; i++ ) no_of_small_prime_numbers++; } mods = m_alloc( no_of_small_prime_numbers * sizeof *mods ); /* make nbits fit into MPI implementation */ nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; val_2 = mpi_alloc_set_ui( 2 ); val_3 = mpi_alloc_set_ui( 3); prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs ); result = mpi_alloc_like( prime ); pminus1= mpi_alloc_like( prime ); ptest = mpi_alloc_like( prime ); count1 = count2 = 0; for(;;) { /* try forvever */ int dotcount=0; /* generate a random number */ { char *p = get_random_bits( nbits, randomlevel, secret ); mpi_set_buffer( prime, p, (nbits+7)/8, 0 ); m_free(p); } /* set high order bit to 1, set low order bit to 1 */ mpi_set_highbit( prime, nbits-1 ); mpi_set_bit( prime, 0 ); /* calculate all remainders */ for(i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); /* now try some primes starting with prime */ for(step=0; step < 20000; step += 2 ) { /* check against all the small primes we have in mods */ count1++; for(i=0; (x = small_prime_numbers[i]); i++ ) { while( mods[i] + step >= x ) mods[i] -= x; if( !(mods[i] + step) ) break; } if( x ) continue; /* found a multiple of an already known prime */ mpi_add_ui( ptest, prime, step ); /* do a faster Fermat test */ count2++; mpi_sub_ui( pminus1, ptest, 1); mpi_powm( result, val_2, pminus1, ptest ); if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */ /* perform stronger tests */ if( is_prime(ptest, 5, &count2 ) ) { if( !mpi_test_bit( ptest, nbits-1 ) ) { progress('\n'); log_debug("overflow in prime generation\n"); break; /* step loop, continue with a new prime */ } mpi_free(val_2); mpi_free(val_3); mpi_free(result); mpi_free(pminus1); mpi_free(prime); m_free(mods); return ptest; } } if( ++dotcount == 10 ) { progress('.'); dotcount = 0; } } progress(':'); /* restart with a new random value */ } }
/**************** * Generate a random secret exponent k from prime p, so that k is * relatively prime to p-1. With SMALL_K set, k will be selected for * better encryption performance - this must never be used signing! */ static gcry_mpi_t gen_k( gcry_mpi_t p, int small_k ) { gcry_mpi_t k = mpi_alloc_secure( 0 ); gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) ); gcry_mpi_t p_1 = mpi_copy(p); unsigned int orig_nbits = mpi_get_nbits(p); unsigned int nbits, nbytes; char *rndbuf = NULL; if (small_k) { /* Using a k much lesser than p is sufficient for encryption and * it greatly improves the encryption performance. We use * Wiener's table and add a large safety margin. */ nbits = wiener_map( orig_nbits ) * 3 / 2; if( nbits >= orig_nbits ) BUG(); } else nbits = orig_nbits; nbytes = (nbits+7)/8; if( DBG_CIPHER ) log_debug("choosing a random k "); mpi_sub_ui( p_1, p, 1); for(;;) { if( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); } else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use this the here maybe it is easier to do this directly in random.c Anyway, it is highly inlikely that we will ever reach this code. */ char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); memcpy( rndbuf, pp, 4 ); gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); for(;;) { if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ { if( DBG_CIPHER ) progress('+'); break; /* no */ } if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ { if( DBG_CIPHER ) progress('-'); break; /* no */ } if (gcry_mpi_gcd( temp, k, p_1 )) goto found; /* okay, k is relative prime to (p-1) */ mpi_add_ui( k, k, 1 ); if( DBG_CIPHER ) progress('.'); } } found: gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); mpi_free(p_1); mpi_free(temp); return k; }
/* Convert the external representation of an integer stored in BUFFER with a length of BUFLEN into a newly create MPI returned in RET_MPI. If NBYTES is not NULL, it will receive the number of bytes actually scanned after a successful operation. */ gcry_error_t gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, const void *buffer_arg, size_t buflen, size_t *nscanned) { const unsigned char *buffer = (const unsigned char*)buffer_arg; struct gcry_mpi *a = NULL; unsigned int len; int secure = (buffer && gcry_is_secure (buffer)); if (format == GCRYMPI_FMT_SSH) len = 0; else len = buflen; if (format == GCRYMPI_FMT_STD) { const unsigned char *s = buffer; a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (len) { a->sign = !!(*s & 0x80); if (a->sign) { /* FIXME: we have to convert from 2compl to magnitude format */ mpi_free (a); return gcry_error (GPG_ERR_INTERNAL); } else _gcry_mpi_set_buffer (a, s, len, 0); } if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_USG) { a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (len) _gcry_mpi_set_buffer (a, buffer, len, 0); if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_PGP) { a = mpi_read_from_buffer (buffer, &len, secure); if (nscanned) *nscanned = len; if (ret_mpi && a) { mpi_normalize (a); *ret_mpi = a; } else if (a) { mpi_free(a); a = NULL; } return a? 0 : gcry_error (GPG_ERR_INV_OBJ); } else if (format == GCRYMPI_FMT_SSH) { const unsigned char *s = buffer; size_t n; /* This test is not strictly necessary and an assert (!len) would be sufficient. We keep this test in case we later allow the BUFLEN argument to act as a sanitiy check. Same below. */ if (len && len < 4) return gcry_error (GPG_ERR_TOO_SHORT); n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); s += 4; if (len) len -= 4; if (len && n > len) return gcry_error (GPG_ERR_TOO_LARGE); a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (n) { a->sign = !!(*s & 0x80); if (a->sign) { /* FIXME: we have to convert from 2compl to magnitude format */ mpi_free(a); return gcry_error (GPG_ERR_INTERNAL); } else _gcry_mpi_set_buffer( a, s, n, 0 ); } if (nscanned) *nscanned = n+4; if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_HEX) { /* We can only handle C strings for now. */ if (buflen) return gcry_error (GPG_ERR_INV_ARG); a = secure? mpi_alloc_secure (0) : mpi_alloc(0); if (mpi_fromstr (a, (const char *)buffer)) { mpi_free (a); return gcry_error (GPG_ERR_INV_OBJ); } if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else return gcry_error (GPG_ERR_INV_ARG); }
mpi_read(IOBUF inp, unsigned *ret_nread, int secure) #endif { int c, i, j; unsigned int nmax = *ret_nread; unsigned nbits, nbytes, nlimbs, nread=0; mpi_limb_t a; MPI val = NULL; if (nread == nmax) goto overflow; if( (c = iobuf_get(inp)) == -1 ) goto leave; nread++; nbits = c << 8; if (nread == nmax) goto overflow; if( (c = iobuf_get(inp)) == -1 ) goto leave; nread++; nbits |= c; if( nbits > MAX_EXTERN_MPI_BITS ) { log_error("mpi too large for this implementation (%u bits)\n", nbits); goto leave; } nbytes = (nbits+7) / 8; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; #ifdef M_DEBUG val = secure? mpi_debug_alloc_secure( nlimbs, info ) : mpi_debug_alloc( nlimbs, info ); #else val = secure? mpi_alloc_secure( nlimbs ) : mpi_alloc( nlimbs ); #endif i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; j= val->nlimbs = nlimbs; val->sign = 0; for( ; j > 0; j-- ) { a = 0; for(; i < BYTES_PER_MPI_LIMB; i++ ) { if (nread == nmax) { #ifdef M_DEBUG mpi_debug_free (val); #else mpi_free (val); #endif val = NULL; goto overflow; } a <<= 8; a |= iobuf_get(inp) & 0xff; nread++; } i = 0; val->d[j-1] = a; } leave: *ret_nread = nread; return val; overflow: log_error ("mpi larger than indicated length (%u bytes)\n", nmax); *ret_nread = nread; return val; }
/* * Generate a random secret exponent K less than Q. * Note that ECDSA uses this code also to generate D. */ gcry_mpi_t _gcry_dsa_gen_k (gcry_mpi_t q, int security_level) { gcry_mpi_t k = mpi_alloc_secure (mpi_get_nlimbs (q)); unsigned int nbits = mpi_get_nbits (q); unsigned int nbytes = (nbits+7)/8; char *rndbuf = NULL; /* To learn why we don't use mpi_mod to get the requested bit size, read the paper: "The Insecurity of the Digital Signature Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ if (DBG_CIPHER) log_debug ("choosing a random k of %u bits at seclevel %d\n", nbits, security_level); for (;;) { if ( !rndbuf || nbits < 32 ) { xfree (rndbuf); rndbuf = _gcry_random_bytes_secure (nbytes, security_level); } else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use these extra bytes here. However the required management code is more complex and thus we better use this simple method. */ char *pp = _gcry_random_bytes_secure (4, security_level); memcpy (rndbuf, pp, 4); xfree (pp); } _gcry_mpi_set_buffer (k, rndbuf, nbytes, 0); /* Make sure we have the requested number of bits. This code looks a bit funny but it is easy to understand if you consider that mpi_set_highbit clears all higher bits. We don't have a clear_highbit, thus we first set the high bit and then clear it again. */ if (mpi_test_bit (k, nbits-1)) mpi_set_highbit (k, nbits-1); else { mpi_set_highbit (k, nbits-1); mpi_clear_bit (k, nbits-1); } if (!(mpi_cmp (k, q) < 0)) /* check: k < q */ { if (DBG_CIPHER) log_debug ("\tk too large - again\n"); continue; /* no */ } if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */ { if (DBG_CIPHER) log_debug ("\tk is zero - again\n"); continue; /* no */ } break; /* okay */ } xfree (rndbuf); return k; }