static void test_keys( ELG_secret_key *sk, unsigned int nbits ) { ELG_public_key pk; MPI test = mpi_alloc( 0 ); MPI out1_a = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out1_b = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out2 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); pk.p = sk->p; pk.g = sk->g; pk.y = sk->y; /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( test, p, (nbits+7)/8, 0 ); xfree(p); } do_encrypt( out1_a, out1_b, test, &pk ); decrypt( out2, out1_a, out1_b, sk ); if( mpi_cmp( test, out2 ) ) log_fatal("Elgamal operation: encrypt, decrypt failed\n"); mpi_free( test ); mpi_free( out1_a ); mpi_free( out1_b ); mpi_free( out2 ); }
MPI do_encode_md(const void *sha_buffer, unsigned nbits) { int nframe = (nbits+7) / 8; uint8_t *frame, *fr_pt; int i = 0, n; size_t asnlen = DIM(asn); MPI a = MPI_NULL; if(SHA1_DIGEST_LENGTH + asnlen + 4 > nframe ) printk("MPI: can't encode a %d bit MD into a %d bits frame\n", (int)(SHA1_DIGEST_LENGTH*8), (int)nbits); /* We encode the MD in this way: * * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) * * PAD consists of FF bytes. */ //daveti: hack //frame = kmalloc(nframe, GFP_KERNEL); frame = kmalloc(nframe, GFP_ATOMIC); if (!frame) return MPI_NULL; n = 0; frame[n++] = 0; frame[n++] = 1; /* block type */ i = nframe - SHA1_DIGEST_LENGTH - asnlen -3 ; if(i <= 1) { printk("MPI: message digest encoding failed\n"); kfree(frame); return a; } memset( frame+n, 0xff, i ); n += i; frame[n++] = 0; memcpy( frame+n, &asn, asnlen ); n += asnlen; memcpy( frame+n, sha_buffer, SHA1_DIGEST_LENGTH ); n += SHA1_DIGEST_LENGTH; i = nframe; fr_pt = frame; if (n != nframe) { printk("MPI: message digest encoding failed, frame length is wrong\n"); kfree(frame); return a; } a = mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); mpi_set_buffer( a, frame, nframe, 0 ); kfree(frame); return a; }
static void test_keys( RSA_secret_key *sk, unsigned nbits ) { RSA_public_key pk; MPI test = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out1 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); MPI out2 = mpi_alloc ( mpi_nlimb_hint_from_nbits (nbits) ); pk.n = sk->n; pk.e = sk->e; { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( test, p, (nbits+7)/8, 0 ); xfree(p); } public( out1, test, &pk );
static void test_keys( RSA_secret_key *sk, unsigned nbits ) { RSA_public_key pk; MPI test = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); MPI out1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); MPI out2 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); pk.n = sk->n; pk.e = sk->e; { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( test, p, (nbits+7)/8, 0 ); m_free(p); } public( out1, test, &pk );
/**************** * 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 ); }
/**************** * 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 bee used signing! */ static MPI gen_k( MPI p, int small_k ) { MPI k = mpi_alloc_secure( 0 ); MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); MPI p_1 = mpi_copy(p); unsigned int orig_nbits = mpi_get_nbits(p); unsigned int nbits; unsigned int 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 of %u bits", nbits); mpi_sub_ui( p_1, p, 1); for(;;) { if( !rndbuf || nbits < 32 ) { xfree(rndbuf); rndbuf = get_random_bits( nbits, 1, 1 ); } else { /* Change only some of the higher bits. */ /* We could impprove this by directly requesting more memory * at the first call to get_random_bits() 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 = get_random_bits( 32, 1, 1 ); memcpy( rndbuf,pp, 4 ); xfree(pp); } 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( mpi_gcd( temp, k, p_1 ) ) goto found; /* okay, k is relatively prime to (p-1) */ mpi_add_ui( k, k, 1 ); if( DBG_CIPHER ) progress('.'); } } found: xfree(rndbuf); if( DBG_CIPHER ) progress('\n'); mpi_free(p_1); mpi_free(temp); return k; }
/**************** * Return true if n is probably a prime */ static int is_prime( MPI n, int steps, int *count ) { MPI x = mpi_alloc( mpi_get_nlimbs( n ) ); MPI y = mpi_alloc( mpi_get_nlimbs( n ) ); MPI z = mpi_alloc( mpi_get_nlimbs( n ) ); MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); MPI a2 = mpi_alloc_set_ui( 2 ); MPI q; unsigned i, j, k; int rc = 0; unsigned nbits = mpi_get_nbits( n ); mpi_sub_ui( nminus1, n, 1 ); /* find q and k, so that n = 1 + 2^k * q */ q = mpi_copy( nminus1 ); k = mpi_trailing_zeros( q ); mpi_tdiv_q_2exp(q, q, k); for(i=0 ; i < steps; i++ ) { ++*count; if( !i ) { mpi_set_ui( x, 2 ); } else { /*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/ { char *p = get_random_bits( nbits, 0, 0 ); mpi_set_buffer( x, p, (nbits+7)/8, 0 ); m_free(p); } /* make sure that the number is smaller than the prime * and keep the randomness of the high bit */ if( mpi_test_bit( x, nbits-2 ) ) { mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */ } else { mpi_set_highbit( x, nbits-2 ); mpi_clear_bit( x, nbits-2 ); } assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); } mpi_powm( y, x, q, n); if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { mpi_powm(y, y, a2, n); if( !mpi_cmp_ui( y, 1 ) ) goto leave; /* not a prime */ } if( mpi_cmp( y, nminus1 ) ) goto leave; /* not a prime */ } progress('+'); } rc = 1; /* may be a prime */ leave: mpi_free( x ); mpi_free( y ); mpi_free( z ); mpi_free( nminus1 ); mpi_free( q ); return rc; }
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 */ } }