From 69cf10ffab3a75d5afdd59f57a772e880b4f2426 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 5 May 1998 20:34:20 +0000 Subject: [PATCH] add DSA key generation --- THANKS | 2 + TODO | 2 + VERSION | 2 +- cipher/ChangeLog | 10 ++++ cipher/dsa.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ cipher/dsa.h | 3 +- cipher/elgamal.c | 4 +- cipher/primegen.c | 53 +++++++++++++++----- cipher/tiger.c | 9 ++-- g10/ChangeLog | 5 ++ g10/build-packet.c | 23 +++++++++ g10/g10.c | 18 +++++-- g10/keyedit.c | 3 ++ g10/keygen.c | 95 ++++++++++++++++++++++++++++++++++-- g10/main.h | 1 + include/cipher.h | 3 +- zlib/Makefile | 2 +- 17 files changed, 324 insertions(+), 29 deletions(-) diff --git a/THANKS b/THANKS index 7bff6b5fe..5078c657e 100644 --- a/THANKS +++ b/THANKS @@ -24,6 +24,8 @@ Ulf M Walter Koch walterk@ddorf.rhein-ruhr.de Werner Koch werner.koch@guug.de Wim Vandeputte bunbun@reptile.rug.ac.be + tzeruch@ceddec.com + Thanks to the German Unix User Group for providing FTP space and Martin Hamilton for hosting the mailing list. diff --git a/TODO b/TODO index bc817672f..78f6a1470 100644 --- a/TODO +++ b/TODO @@ -47,3 +47,5 @@ * add readline support (but how can we allcoate it in secure memory?) + * add a testcase for --print-mds + diff --git a/VERSION b/VERSION index 0fcb3bba7..fc15b1bc3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.17 +0.2.17a diff --git a/cipher/ChangeLog b/cipher/ChangeLog index a44abae94..ae96007a1 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,13 @@ +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c (cipher_get_keylen): New. diff --git a/cipher/dsa.c b/cipher/dsa.c index f32fee649..d1c15c41c 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "util.h" #include "mpi.h" #include "cipher.h" @@ -74,6 +75,123 @@ dsa_free_secret_key( DSA_secret_key *sk ) } +static void +test_keys( DSA_public_key *pk, DSA_secret_key *sk, unsigned qbits ) +{ + MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + + mpi_set_bytes( test, qbits, get_random_byte, 0 ); + + dsa_sign( out1_a, out1_b, test, sk ); + if( !dsa_verify( out1_a, out1_b, test, pk ) ) + log_fatal("DSA:: sign, verify failed\n"); + + mpi_free( test ); + mpi_free( out1_a ); + mpi_free( out1_b ); +} + + + +/**************** + * Generate a DSA key pair with a key of size NBITS + * Returns: 2 structures filled with all needed values + * and an array with the n-1 factors of (p-1) + */ +void +dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, + unsigned nbits, MPI **ret_factors ) +{ + MPI p; /* the prime */ + MPI q; /* the 160 bit prime factor */ + MPI g; /* the generator */ + MPI y; /* g^x mod p */ + MPI x; /* the secret exponent */ + MPI h, e; /* helper */ + unsigned qbits; + byte *rndbuf; + + assert( nbits >= 512 && nbits <= 1024 ); + + qbits = 160; + p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors ); + /* get q out of factors */ + q = mpi_copy((*ret_factors)[0]); + if( mpi_get_nbits(q) != qbits ) + BUG(); + + /* find a generator g (h and e are helpers)*/ + /* e = (p-1)/q */ + e = mpi_alloc( mpi_get_nlimbs(p) ); + mpi_sub_ui( e, p, 1 ); + mpi_fdiv_q( e, e, q ); + g = mpi_alloc( mpi_get_nlimbs(p) ); + h = mpi_alloc_set_ui( 1 ); /* we start with 2 */ + do { + mpi_add_ui( h, h, 1 ); + /* g = h^e mod p */ + mpi_powm( g, h, e, p ); + } while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */ + + /* select a random number which has these properties: + * 0 < x < q-1 + * This must be a very good random number because this + * is the secret part. */ + if( DBG_CIPHER ) + log_debug("choosing a random x "); + assert( qbits >= 16 ); + x = mpi_alloc_secure( mpi_get_nlimbs(q) ); + mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ + rndbuf = NULL; + do { + if( DBG_CIPHER ) + fputc('.', stderr); + if( !rndbuf ) + rndbuf = get_random_bits( qbits, 2, 1 ); + else { /* change only some of the higher bits (= 2 bytes)*/ + char *r = get_random_bits( 16, 2, 1 ); + memcpy(rndbuf, r, 16/8 ); + m_free(r); + } + mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); + mpi_clear_highbit( x, qbits+1 ); + } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); + m_free(rndbuf); + mpi_free( e ); + mpi_free( h ); + + /* y = g^x mod p */ + y = mpi_alloc( mpi_get_nlimbs(p) ); + mpi_powm( y, g, x, p ); + + if( DBG_CIPHER ) { + fputc('\n', stderr); + log_mpidump("dsa p= ", p ); + log_mpidump("dsa q= ", q ); + log_mpidump("dsa g= ", g ); + log_mpidump("dsa y= ", y ); + log_mpidump("dsa x= ", x ); + } + + /* copy the stuff to the key structures */ + pk->p = mpi_copy(p); + pk->q = mpi_copy(q); + pk->g = mpi_copy(g); + pk->y = mpi_copy(y); + sk->p = p; + sk->q = q; + sk->g = g; + sk->y = y; + sk->x = x; + + /* now we can test our keys (this should never fail!) */ + test_keys( pk, sk, qbits ); +} + + + /**************** * Test whether the secret key is valid. * Returns: if this is a valid key. diff --git a/cipher/dsa.h b/cipher/dsa.h index 07a41ae6c..2d38a7388 100644 --- a/cipher/dsa.h +++ b/cipher/dsa.h @@ -41,8 +41,9 @@ typedef struct { void dsa_free_public_key( DSA_public_key *pk ); void dsa_free_secret_key( DSA_secret_key *sk ); -void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, unsigned nbits ); int dsa_check_secret_key( DSA_secret_key *sk ); +void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, + unsigned nbits, MPI **ret_factors ); void dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey); int dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); diff --git a/cipher/elgamal.c b/cipher/elgamal.c index ac02bde52..7fad35c56 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -139,7 +139,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, else qbits = 240; g = mpi_alloc(1); - p = generate_elg_prime( nbits, qbits, g, ret_factors ); + p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui(p_min1, p, 1); @@ -163,7 +163,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, } else { char *r = get_random_bits( 16, 2, 1 ); - memcpy(rndbuf, r, 16 ); + memcpy(rndbuf, r, 16/8 ); m_free(r); } } diff --git a/cipher/primegen.c b/cipher/primegen.c index 6ebaffe6a..26d21acb9 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -63,37 +63,49 @@ generate_public_prime( unsigned nbits ) * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. + * + * mode 0: Standard + * 1: Make sure that at least one factor is of size qbits. */ MPI -generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) +generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **ret_factors ) { int n; /* number of factors */ int m; /* number of primes in pool */ unsigned fbits; /* length of prime factors */ MPI *factors; /* current factors */ MPI *pool; /* pool of primes */ - MPI q; /* first prime factor */ + MPI q; /* first prime factor (variable)*/ MPI prime; /* prime test value */ + MPI q_factor; /* used for mode 1 */ byte *perms = NULL; int i, j; int count1, count2; unsigned nprime; + unsigned req_qbits = qbits; /* the requested q bits size */ /* find number of needed prime factors */ for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) ; n--; - if( !n ) + if( !n || (mode==1 && n < 2) ) log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits ); - fbits = (pbits - qbits -1) / n; - while( qbits + n*fbits < pbits ) - qbits++; + if( mode == 1 ) { + n--; + fbits = (pbits - 2*req_qbits -1) / n; + qbits = pbits - req_qbits - n*fbits; + } + else { + fbits = (pbits - req_qbits -1) / n; + qbits = pbits - n*fbits; + } if( DBG_CIPHER ) - log_debug("gen prime: pbits=%u qbits=%u fbits=%u n=%d\n", - pbits, qbits, fbits, n ); - + log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", + pbits, req_qbits, qbits, fbits, n ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); q = gen_prime( qbits, 0, 1 ); + q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = m_alloc_clear( (n+2) * sizeof *factors ); @@ -139,6 +151,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) mpi_set( prime, q ); mpi_mul_ui( prime, prime, 2 ); + if( mode == 1 ) + mpi_mul( prime, prime, q_factor ); for(i=0; i < n; i++ ) mpi_mul( prime, prime, factors[i] ); mpi_add_ui( prime, prime, 1 ); @@ -171,18 +185,30 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) putc('\n', stderr); log_mpidump( "prime : ", prime ); log_mpidump( "factor q: ", q ); + if( mode == 1 ) + log_mpidump( "factor q0: ", q_factor ); for(i=0; i < n; i++ ) log_mpidump( "factor pi: ", factors[i] ); log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); + if( mode == 1 ) + fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) ); for(i=0; i < n; i++ ) fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); putc('\n', stderr); } if( ret_factors ) { /* caller wants the factors */ - *ret_factors = m_alloc_clear( (n+1) * sizeof **ret_factors ); - for(i=0; i < n; i++ ) - (*ret_factors)[i] = mpi_copy( factors[i] ); + *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors); + if( mode == 1 ) { + i = 0; + (*ret_factors)[i++] = mpi_copy( q_factor ); + for(; i <= n; i++ ) + (*ret_factors)[i] = mpi_copy( factors[i] ); + } + else { + for(; i < n; i++ ) + (*ret_factors)[i] = mpi_copy( factors[i] ); + } } if( g ) { /* create a generator (start with 3)*/ @@ -190,6 +216,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) MPI b = mpi_alloc( mpi_get_nlimbs(prime) ); MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) ); + if( mode == 1 ) + BUG(); /* not yet implemented */ factors[n] = q; factors[n+1] = mpi_alloc_set_ui(2); mpi_sub_ui( pmin1, prime, 1 ); @@ -230,6 +258,7 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) } + static MPI gen_prime( unsigned nbits, int secret, int randomlevel ) { diff --git a/cipher/tiger.c b/cipher/tiger.c index 3ceeb9fdd..69770258c 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -702,10 +702,11 @@ transform( TIGER_CONTEXT *hd, byte *data ) u64 a,b,c,aa,bb,cc; u64 x[8]; #ifdef BIG_ENDIAN_HOST - #define MKWORD(d,n) ( (d)[8*(n)+0] << 56 | (d)[8*(n)+1] << 48 \ - | (d)[8*(n)+2] << 40 | (d)[8*(n)+3] << 32 \ - | (d)[8*(n)+4] << 24 | (d)[8*(n)+5] << 16 \ - | (d)[8*(n)+6] << 8 | (d)[8*(n)+7] ) + #define MKWORD(d,n) \ + ( ((u64)(d)[8*(n)+0]) << 56 | ((u64)(d)[8*(n)+1]) << 48 \ + | ((u64)(d)[8*(n)+2]) << 40 | ((u64)(d)[8*(n)+3]) << 32 \ + | ((u64)(d)[8*(n)+4]) << 24 | ((u64)(d)[8*(n)+5]) << 16 \ + | ((u64)(d)[8*(n)+6]) << 8 | ((u64)(d)[8*(n)+7]) ) x[0] = MKWORD(data, 0); x[1] = MKWORD(data, 1); x[2] = MKWORD(data, 2); diff --git a/g10/ChangeLog b/g10/ChangeLog index b61ea5cda..e69f10865 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +Tue May 5 22:11:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (gen_dsa): New. + * build_packet.c (do_secret_cert): Support for DSA + Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) * compress.c: doubled buffer sizes diff --git a/g10/build-packet.c b/g10/build-packet.c index 07aaf0676..da6e413ac 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -292,6 +292,29 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) mpi_write(a, skc->d.elg.x ); write_16(a, skc->csum ); } + else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) { + mpi_write(a, skc->d.dsa.p ); + mpi_write(a, skc->d.dsa.q ); + mpi_write(a, skc->d.dsa.g ); + mpi_write(a, skc->d.dsa.y ); + if( skc->is_protected ) { + iobuf_put(a, 0xff ); + iobuf_put(a, skc->protect.algo ); + iobuf_put(a, skc->protect.s2k.mode ); + iobuf_put(a, skc->protect.s2k.hash_algo ); + if( skc->protect.s2k.mode == 1 + || skc->protect.s2k.mode == 4 ) + iobuf_write(a, skc->protect.s2k.salt, 8 ); + if( skc->protect.s2k.mode == 4 ) + write_32(a, skc->protect.s2k.count ); + iobuf_write(a, skc->protect.iv, 8 ); + } + else + iobuf_put(a, 0 ); + + mpi_write(a, skc->d.dsa.x ); + write_16(a, skc->csum ); + } else if( is_RSA(skc->pubkey_algo) ) { mpi_write(a, skc->d.rsa.n ); mpi_write(a, skc->d.rsa.e ); diff --git a/g10/g10.c b/g10/g10.c index c068b5b36..fdcd4623c 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -72,6 +72,7 @@ static ARGPARSE_OPTS opts[] = { { 515, "fingerprint", 0, N_("list keys and fingerprints")}, #ifdef IS_G10 { 503, "gen-key", 0, N_("generate a new key pair")}, + { 554, "add-key", 0, N_("add a subkey to a key pair")}, { 506, "sign-key" ,0, N_("make a signature on a key in the keyring")}, { 505, "delete-key",0, N_("remove key from the public keyring")}, { 524, "edit-key" ,0, N_("edit a key signature")}, @@ -171,7 +172,7 @@ enum cmd_values { aNull = 0, aSym, aStore, aEncr, aKeygen, aSign, aSignEncr, aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, aDeleteSecretKey, aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys, - aListSigs, + aListSigs, aKeyadd, aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs, aListTrustDB, aListTrustPath, aDeArmor, aEnArmor, aGenRandom, aTest, aNOP }; @@ -574,6 +575,7 @@ main( int argc, char **argv ) case 551: set_cmd( &cmd, aListKeys); break; case 552: set_cmd( &cmd, aListSigs); break; case 553: opt.skip_verify=1; break; + case 554: set_cmd( &cmd, aKeyadd); break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -817,6 +819,11 @@ main( int argc, char **argv ) wrong_args("--gen-key"); generate_keypair(); break; + case aKeyadd: /* add a subkey (interactive) */ + if( argc != 1 ) + wrong_args("--add-key userid"); + generate_subkeypair(*argv); + break; #endif case aImport: @@ -873,19 +880,24 @@ main( int argc, char **argv ) putchar('\n'); } else if( argc == 2 ) { - mpi_print( stdout, generate_elg_prime( atoi(argv[0]), + mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]), atoi(argv[1]), NULL,NULL ), 1); putchar('\n'); } else if( argc == 3 ) { MPI g = mpi_alloc(1); - mpi_print( stdout, generate_elg_prime( atoi(argv[0]), + mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]), atoi(argv[1]), g, NULL ), 1); printf("\nGenerator: "); mpi_print( stdout, g, 1 ); putchar('\n'); mpi_free(g); } + else if( argc == 4 ) { + mpi_print( stdout, generate_elg_prime( 1, atoi(argv[0]), + atoi(argv[1]), NULL,NULL ), 1); + putchar('\n'); + } else usage(1); break; diff --git a/g10/keyedit.c b/g10/keyedit.c index 0a4afbf43..a475ed813 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -621,6 +621,8 @@ change_passphrase( const char *username ) break; } + /* fixme: unprotect all subkeys */ + if( rc ) tty_printf("Can't edit this key: %s\n", g10_errstr(rc)); else { @@ -648,6 +650,7 @@ change_passphrase( const char *username ) break; } else { /* okay */ + /* fixme: protect all subkeys too */ skc->protect.algo = dek->algo; skc->protect.s2k = *s2k; rc = protect_secret_key( skc, dek ); diff --git a/g10/keygen.c b/g10/keygen.c index e714c1605..771dcb36c 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -224,11 +224,84 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, #endif /*ENABLE_RSA_KEYGEN*/ +/**************** + * Generate a DSA key + */ static int gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days ) + STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days ) { - return G10ERR_GENERAL; + int rc; + int i; + PACKET *pkt; + PKT_secret_cert *skc; + PKT_public_cert *pkc; + DSA_public_key pk; + DSA_secret_key sk; + MPI *factors; + + if( nbits > 1024 ) + nbits = 1024; + + dsa_generate( &pk, &sk, nbits, &factors ); + + skc = m_alloc_clear( sizeof *skc ); + pkc = m_alloc_clear( sizeof *pkc ); + skc->timestamp = pkc->timestamp = make_timestamp(); + skc->version = pkc->version = 4; + /* valid days are not stored in the packet, but it is + * used here to put it into the signature. + */ + skc->valid_days = pkc->valid_days = valid_days; + skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_DSA; + pkc->d.dsa.p = pk.p; + pkc->d.dsa.q = pk.q; + pkc->d.dsa.g = pk.g; + pkc->d.dsa.y = pk.y; + skc->d.dsa.p = sk.p; + skc->d.dsa.q = sk.q; + skc->d.dsa.g = sk.g; + skc->d.dsa.y = sk.y; + skc->d.dsa.x = sk.x; + skc->is_protected = 0; + skc->protect.algo = 0; + + skc->csum = checksum_mpi( skc->d.dsa.x ); + /* return an unprotected version of the skc */ + *ret_skc = copy_secret_cert( NULL, skc ); + + if( dek ) { + skc->protect.algo = dek->algo; + skc->protect.s2k = *s2k; + rc = protect_secret_key( skc, dek ); + if( rc ) { + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + free_public_cert(pkc); + free_secret_cert(skc); + return rc; + } + } + + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = PKT_PUBLIC_CERT; + pkt->pkt.public_cert = pkc; + add_kbnode(pub_root, new_kbnode( pkt )); + + /* don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret) + * p = 2 * q * f1 * f2 * ... * fn + * We store only f1 to f_n-1 - fn can be calculated because p and q + * are known. + */ + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = PKT_SECRET_CERT; + pkt->pkt.secret_cert = skc; + add_kbnode(sec_root, new_kbnode( pkt )); + for(i=1; factors[i]; i++ ) /* the first one is q */ + add_kbnode( sec_root, + make_mpi_comment_node("#:DSA_factor:", factors[i] )); + + return 0; } @@ -312,7 +385,7 @@ generate_keypair() else if( algo == 2 ) { algo = PUBKEY_ALGO_DSA; algo_name = "DSA"; - tty_printf(_("Sorry; DSA key generation is not yet supported.\n")); + break; } #ifdef ENABLE_RSA_KEYGEN else if( algo == 3 ) { @@ -380,6 +453,10 @@ generate_keypair() " w = key expires in n weeks\n" " m = key expires in n months\n" " y = key expires in n years\n")); + /* Note: The elgamal subkey for DSA has no exiration date because + * is must be signed with the DSA key and this one has the expiration + * date */ + answer = NULL; for(;;) { int mult; @@ -578,7 +655,7 @@ generate_keypair() rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days ); #endif else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days ); + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days); else BUG(); if( !rc ) { @@ -663,3 +740,13 @@ generate_keypair() m_free(sec_fname); } + +/**************** + * add a new subkey to an existing key. + */ +void +generate_subkeypair( const char *userid ) +{ + log_fatal("To be implemented :-)\n"); +} + diff --git a/g10/main.h b/g10/main.h index 9a1ae4ddb..03436d058 100644 --- a/g10/main.h +++ b/g10/main.h @@ -70,6 +70,7 @@ int change_passphrase( const char *username ); /*-- keygen.c --*/ void generate_keypair(void); +void generate_subkeypair(const char *userid); /*-- openfile.c --*/ int overwrite_filep( const char *fname ); diff --git a/include/cipher.h b/include/cipher.h index b64d234db..a78426bb5 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -114,7 +114,8 @@ extern ushort small_prime_numbers[]; /*-- primegen.c --*/ MPI generate_secret_prime( unsigned nbits ); MPI generate_public_prime( unsigned nbits ); -MPI generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **factors ); +MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **factors ); #endif /*G10_CIPHER_H*/ diff --git a/zlib/Makefile b/zlib/Makefile index 8ae5caf9d..4add32d3e 100644 --- a/zlib/Makefile +++ b/zlib/Makefile @@ -93,7 +93,7 @@ POSUB = po RANLIB = ranlib USE_INCLUDED_LIBINTL = yes USE_NLS = yes -VERSION = 0.2.17 +VERSION = 0.2.17a ZLIBS = l =