fingerprints and self signatures added
authorWerner Koch <wk@gnupg.org>
Tue, 9 Dec 1997 12:46:23 +0000 (12:46 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 9 Dec 1997 12:46:23 +0000 (12:46 +0000)
23 files changed:
TODO
cipher/elgamal.c
cipher/primegen.c
cipher/rsa.c
cipher/rsa.h
g10/build-packet.c
g10/free-packet.c
g10/g10.c
g10/keydb.h
g10/keygen.c
g10/keyid.c
g10/mainproc.c
g10/options.h
g10/packet.h
g10/parse-packet.c
g10/passphrase.c
g10/seckey-cert.c
g10/sig-check.c
include/errors.h
include/memory.h
include/mpi.h
mpi/mpicoder.c
util/memory.c

diff --git a/TODO b/TODO
index 03f4faa..21e51d0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,15 +4,13 @@
       this shoud espceially done for the buffer in the chain.
     * add a way to difference between errors and eof in the underflow/flush
       function of iobuf.
-    * filter all output read from the input when displaying it to the user.
+    * check that all output is filtered when displayed.
     * keyring editing
     * add trust stuff
     * make ttyio.c work (hide passwords etc..)
-    * add detached signatures
     * add option file handling.
     * use correct ASN values for DEK encoding
     * add checking of armor trailers
-    * fix the memory stuff (secure memory)
     * add real secure memory
     * look for a way to reuse RSA signatures
     * find a way to remove the armor filter after it
     * enable a SIGSEGV handler while using zlib functions
 
     * PGP writes the signature and then the file, this is not
-      a good idea, we can't write such files if we take input rom stdin.
+      a good idea, we can't write such files if we take input from stdin.
       So the solution will: accept such packet, but write
       signature the corret way: first the data and then the signature[s]
       this is much easier to check, also we must read the entire data
       before we can check wether we have the pubkey or not.  The one-pass
       signature packets should be implemented to avoid this.
 
+    * compress does not work always!
+
index a7450e0..63ec06f 100644 (file)
@@ -95,7 +95,7 @@ gen_k( MPI p )
        if( DBG_CIPHER )
            fputc('.', stderr);
        mpi_set_bytes( k, nbits, get_random_byte, 1 );
-       mpi_set_bit( k, nbits-1 ); /* make sure it's high (needed?) */
+       mpi_set_bit( k, nbits-1 ); /* make sure it's high (really needed?) */
        if( mpi_cmp( k, p_1 ) >= 0 )
            continue; /* is not smaller than (p-1) */
        if( mpi_gcd( temp, k, p_1 ) )
@@ -136,7 +136,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
            fputc('.', stderr);
        mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */
        mpi_set_bit( x, nbits-1 ); /* make sure it's high (needed?) */
-    } while( mpi_cmp( x, p ) >= 0 );  /* x must be samller than p */
+    } while( mpi_cmp( x, p ) >= 0 );  /* x must be smaller than p */
 
     y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
     mpi_powm( y, g, x, p );
index d69f09a..49ec8f6 100644 (file)
@@ -98,8 +98,7 @@ gen_prime( unsigned  nbits, int secret )
            }
            if( x )
                continue;   /* found a multiple of a already known prime */
-           if( DBG_CIPHER )
-               fputc('.', stderr);
+           fputc('.', stderr);
 
            mpi_add_ui( prime, prime, step );
 
@@ -108,8 +107,7 @@ gen_prime( unsigned  nbits, int secret )
            mpi_powm( result, val_2, prime, prime );
            if( mpi_cmp_ui(result, 2) )
                continue;  /* stepping (fermat test failed) */
-           if( DBG_CIPHER )
-               fputc('+', stderr);
+           fputc('+', stderr);
 
            /* perform stronger tests */
            if( !is_not_prime(prime, nbits, 5, &count2 ) ) {
@@ -120,8 +118,9 @@ gen_prime( unsigned  nbits, int secret )
                        break; /* step loop, cont with a new prime */
                    }
                }
+
+               fputc('\n', stderr);
                if( DBG_CIPHER ) {
-                   fputc('\n', stderr);
                    log_debug("performed %u simple and %u stronger tests\n",
                                        count1, count2 );
                    log_mpidump("found prime: ", prime );
@@ -134,8 +133,7 @@ gen_prime( unsigned  nbits, int secret )
                return prime;
            }
        }
-       if( DBG_CIPHER )
-           fputc(':', stderr); /* restart with a new random value */
+       fputc(':', stderr); /* restart with a new random value */
     }
 }
 
@@ -179,8 +177,7 @@ is_not_prime( MPI n, unsigned nbits, int steps, int *count )
            if( j == k )
                goto leave;
        }
-       if( DBG_CIPHER )
-           fputc('+', stderr);
+       fputc('+', stderr);
     }
     rc = 0; /* may be a prime */
 
index a1f0845..db82b48 100644 (file)
@@ -157,6 +157,22 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
 }
 
 
+/****************
+ * Test wether the secret key is valid.
+ * Returns: true if this is a valid key.
+ */
+int
+rsa_check_secret_key( RSA_secret_key *sk )
+{
+    int rc;
+    MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
+
+    mpi_mul(temp, sk->p, sk->q );
+    rc = mpi_cmp( temp, sk->n );
+    mpi_free(temp);
+    return !rc;
+}
+
 
 
 /****************
index a9980d0..1b6d189 100644 (file)
@@ -46,6 +46,7 @@ typedef struct {
 void rsa_free_public_key( RSA_public_key *pk );
 void rsa_free_secret_key( RSA_secret_key *sk );
 void rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits );
+int  rsa_check_secret_key( RSA_secret_key *sk );
 void rsa_public(MPI output, MPI input, RSA_public_key *skey );
 void rsa_secret(MPI output, MPI input, RSA_secret_key *skey );
 
index 6d9957f..25d708c 100644 (file)
@@ -169,13 +169,13 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
     write_16(a, pkc->valid_days );
     iobuf_put(a, pkc->pubkey_algo );
     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
-       mpi_encode(a, pkc->d.elg.p );
-       mpi_encode(a, pkc->d.elg.g );
-       mpi_encode(a, pkc->d.elg.y );
+       mpi_write(a, pkc->d.elg.p );
+       mpi_write(a, pkc->d.elg.g );
+       mpi_write(a, pkc->d.elg.y );
     }
     else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
-       mpi_encode(a, pkc->d.rsa.rsa_n );
-       mpi_encode(a, pkc->d.rsa.rsa_e );
+       mpi_write(a, pkc->d.rsa.rsa_n );
+       mpi_write(a, pkc->d.rsa.rsa_e );
     }
     else {
        rc = G10ERR_PUBKEY_ALGO;
@@ -191,6 +191,31 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
     return rc;
 }
 
+
+/****************
+ * Make a hash value from the public key certificate
+ */
+void
+hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc )
+{
+    PACKET pkt;
+    int rc = 0;
+    int c;
+    IOBUF a = iobuf_temp();
+
+    /* build the packet */
+    init_packet(&pkt);
+    pkt.pkttype = PKT_PUBLIC_CERT;
+    pkt.pkt.public_cert = pkc;
+    if( (rc = build_packet( a, &pkt )) )
+       log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc));
+    while( (c=iobuf_get(a)) != -1 )
+       md_putchar( md, c );
+
+    iobuf_cancel(a);
+}
+
+
 static int
 do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
 {
@@ -202,48 +227,33 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
     write_16(a, skc->valid_days );
     iobuf_put(a, skc->pubkey_algo );
     if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
-       mpi_encode(a, skc->d.elg.p );
-       mpi_encode(a, skc->d.elg.g );
-       mpi_encode(a, skc->d.elg.y );
+       mpi_write(a, skc->d.elg.p );
+       mpi_write(a, skc->d.elg.g );
+       mpi_write(a, skc->d.elg.y );
        iobuf_put(a, skc->d.elg.protect_algo );
-       skc->d.elg.calc_csum = 0;
        if( skc->d.elg.protect_algo ) {
            assert( skc->d.elg.is_protected == 1 );
            assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH );
            iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 );
-           mpi_write_csum(a, (byte*)skc->d.elg.x, &skc->d.elg.calc_csum );
-       }
-       else {  /* not protected */
-           assert( !skc->d.elg.is_protected );
-           mpi_encode_csum(a, skc->d.elg.x, &skc->d.elg.calc_csum );
        }
 
-       write_16(a, skc->d.elg.calc_csum );
+       mpi_write(a, skc->d.elg.x );
+       write_16(a, skc->d.elg.csum );
     }
     else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
-       mpi_encode(a, skc->d.rsa.rsa_n );
-       mpi_encode(a, skc->d.rsa.rsa_e );
+       mpi_write(a, skc->d.rsa.rsa_n );
+       mpi_write(a, skc->d.rsa.rsa_e );
        iobuf_put(a, skc->d.rsa.protect_algo );
-       skc->d.rsa.calc_csum = 0;
        if( skc->d.rsa.protect_algo ) {
            assert( skc->d.rsa.is_protected == 1 );
            assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH );
            iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 );
-
-           mpi_write_csum(a, (byte*)skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
-           mpi_write_csum(a, (byte*)skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
-           mpi_write_csum(a, (byte*)skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
-           mpi_write_csum(a, (byte*)skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
-       }
-       else {  /* Not protected: You fool you! */
-           assert( !skc->d.rsa.is_protected );
-           mpi_encode_csum(a, skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
-           mpi_encode_csum(a, skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
-           mpi_encode_csum(a, skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
-           mpi_encode_csum(a, skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
        }
-
-       write_16(a, skc->d.rsa.calc_csum );
+       mpi_write(a, skc->d.rsa.rsa_d );
+       mpi_write(a, skc->d.rsa.rsa_p );
+       mpi_write(a, skc->d.rsa.rsa_q );
+       mpi_write(a, skc->d.rsa.rsa_u );
+       write_16(a, skc->d.rsa.csum );
     }
     else {
        rc = G10ERR_PUBKEY_ALGO;
@@ -270,11 +280,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
     write_32(a, enc->keyid[1] );
     iobuf_put(a,enc->pubkey_algo );
     if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
-       mpi_encode(a, enc->d.elg.a );
-       mpi_encode(a, enc->d.elg.b );
+       mpi_write(a, enc->d.elg.a );
+       mpi_write(a, enc->d.elg.b );
     }
     else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
-       mpi_encode(a, enc->d.rsa.rsa_integer );
+       mpi_write(a, enc->d.rsa.rsa_integer );
     }
     else {
        rc = G10ERR_PUBKEY_ALGO;
@@ -379,14 +389,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
        iobuf_put(a, sig->d.elg.digest_algo );
        iobuf_put(a, sig->d.elg.digest_start[0] );
        iobuf_put(a, sig->d.elg.digest_start[1] );
-       mpi_encode(a, sig->d.elg.a );
-       mpi_encode(a, sig->d.elg.b );
+       mpi_write(a, sig->d.elg.a );
+       mpi_write(a, sig->d.elg.b );
     }
     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
        iobuf_put(a, sig->d.rsa.digest_algo );
        iobuf_put(a, sig->d.rsa.digest_start[0] );
        iobuf_put(a, sig->d.rsa.digest_start[1] );
-       mpi_encode(a, sig->d.rsa.rsa_integer );
+       mpi_write(a, sig->d.rsa.rsa_integer );
     }
     else {
        rc = G10ERR_PUBKEY_ALGO;
index fa116ba..dfd6f4b 100644 (file)
@@ -100,26 +100,15 @@ free_secret_cert( PKT_secret_cert *cert )
        mpi_free( cert->d.elg.p );
        mpi_free( cert->d.elg.g );
        mpi_free( cert->d.elg.y );
-       if( cert->d.rsa.is_protected )
-           m_free( cert->d.elg.x );
-       else
-           mpi_free( cert->d.elg.x );
+       mpi_free( cert->d.elg.x );
     }
     else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
        mpi_free( cert->d.rsa.rsa_n );
        mpi_free( cert->d.rsa.rsa_e );
-       if( cert->d.rsa.is_protected ) {
-           m_free( cert->d.rsa.rsa_d );
-           m_free( cert->d.rsa.rsa_p );
-           m_free( cert->d.rsa.rsa_q );
-           m_free( cert->d.rsa.rsa_u );
-       }
-       else {
-           mpi_free( cert->d.rsa.rsa_d );
-           mpi_free( cert->d.rsa.rsa_p );
-           mpi_free( cert->d.rsa.rsa_q );
-           mpi_free( cert->d.rsa.rsa_u );
-       }
+       mpi_free( cert->d.rsa.rsa_d );
+       mpi_free( cert->d.rsa.rsa_p );
+       mpi_free( cert->d.rsa.rsa_q );
+       mpi_free( cert->d.rsa.rsa_u );
     }
     m_free(cert);
 }
index 747cba1..88bde47 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -124,6 +124,8 @@ main( int argc, char **argv )
     { 512, "cache-all" ,0, "hold everything in memory"},
     { 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
     { 514, "test"      , 0, "\rdevelopment usage" },
+    { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
+    { 515, "fingerprint", 0, "show the fingerprints"},
     {0} };
     ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
     IOBUF a;
@@ -136,11 +138,14 @@ main( int argc, char **argv )
     int nrings=0;
     armor_filter_context_t afx;
     const char *s;
+    int detached_sig = 0;
 
     opt.compress = -1; /* defaults to default compression level */
     while( arg_parse( &pargs, opts) ) {
        switch( pargs.r_opt ) {
-         case 'v': opt.verbose++; break;
+         case 'v': opt.verbose++;
+                   opt.list_sigs=1;
+                   break;
          case 'z':
            opt.compress = pargs.r.ret_int;
            break;
@@ -151,7 +156,7 @@ main( int argc, char **argv )
                        opt.outfile_is_stdout = 1;
                    break;
          case 'e': action = action == aSign? aSignEncr : aEncr; break;
-         case 'b': opt.detached_sig = 1;
+         case 'b': detached_sig = 1;
               /* fall trough */
          case 's': action = action == aEncr? aSignEncr : aSign;  break;
          case 'l': /* store the local users */
@@ -171,13 +176,14 @@ main( int argc, char **argv )
          case 502: opt.answer_no = 1; break;
          case 503: action = aKeygen; break;
          case 507: action = aStore; break;
-         case 508: opt.check_sigs = 1; break;
+         case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
          case 509: add_keyring(pargs.r.ret_str); nrings++; break;
          case 510: opt.debug |= pargs.r.ret_ulong; break;
          case 511: opt.debug = ~0; break;
          case 512: opt.cache_all = 1; break;
          case 513: action = aPrimegen; break;
          case 514: action = aTest; break;
+         case 515: opt.fingerprint = 1; break;
          default : pargs.err = 2; break;
        }
     }
@@ -230,7 +236,7 @@ main( int argc, char **argv )
       case aSign: /* sign the given file */
        if( argc > 1 )
            usage(1);
-       if( (rc = sign_file(fname, opt.detached_sig, locusr)) )
+       if( (rc = sign_file(fname, detached_sig, locusr)) )
            log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
        break;
 
index 21423cf..bd89280 100644 (file)
@@ -50,6 +50,8 @@ unsigned nbits_from_skc( PKT_secret_cert *skc );
 const char *datestr_from_pkc( PKT_public_cert *pkc );
 const char *datestr_from_skc( PKT_secret_cert *skc );
 const char *datestr_from_sig( PKT_signature *sig );
+byte *fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len );
+byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
 
 
 
index 3cbbf89..a4ed697 100644 (file)
@@ -51,9 +51,44 @@ answer_is_yes( const char *s )
 }
 
 
+static u16
+checksum_u16( unsigned n )
+{
+    u16 a;
+
+    a  = (n >> 8) & 0xff;
+    a |= n & 0xff;
+    return a;
+}
+
+static u16
+checksum( byte *p, unsigned n )
+{
+    u16 a;
+
+    for(a=0; n; n-- )
+       a += *p++;
+    return a;
+}
+
+static u16
+checksum_mpi( MPI a )
+{
+    u16 csum;
+    byte *buffer;
+    unsigned nbytes;
+
+    buffer = mpi_get_buffer( a, &nbytes, NULL );
+    csum = checksum_u16( nbytes*8 );
+    csum += checksum( buffer, nbytes );
+    m_free( buffer );
+    return csum;
+}
+
+
 
 static void
-write_uid( IOBUF out, const char *s )
+write_uid( IOBUF out, const char *s, PKT_user_id **upkt )
 {
     PACKET pkt;
     size_t n = strlen(s);
@@ -65,13 +100,44 @@ write_uid( IOBUF out, const char *s )
     strcpy(pkt.pkt.user_id->name, s);
     if( (rc = build_packet( out, &pkt )) )
        log_error("build_packet(user_id) failed: %s\n", g10_errstr(rc) );
+    if( upkt ) {
+       *upkt = pkt.pkt.user_id;
+       pkt.pkt.user_id = NULL;
+    }
     free_packet( &pkt );
 }
 
 
+static int
+write_selfsig( IOBUF out, PKT_public_cert *pkc, PKT_user_id *uid,
+                                               PKT_secret_cert *skc )
+{
+    PACKET pkt;
+    PKT_signature *sig;
+    int rc=0;
+
+    if( opt.verbose )
+       log_info("writing self signature\n");
+
+    rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, DIGEST_ALGO_RMD160 );
+    if( rc ) {
+       log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
+       return rc;
+    }
+
+    pkt.pkttype = PKT_SIGNATURE;
+    pkt.pkt.signature = sig;
+    if( (rc = build_packet( out, &pkt )) )
+       log_error("build_packet(signature) failed: %s\n", g10_errstr(rc) );
+    free_packet( &pkt );
+    return rc;
+}
+
+
 #ifdef HAVE_RSA_CIPHER
 static int
-gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
+gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
+       PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
 {
     int rc;
     PACKET pkt1, pkt2;
@@ -80,6 +146,9 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
     RSA_public_key pk;
     RSA_secret_key sk;
 
+    init_packet(&pkt1);
+    init_packet(&pkt2);
+
     rsa_generate( &pk, &sk, nbits );
 
     skc = m_alloc( sizeof *skc );
@@ -96,15 +165,28 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
     skc->d.rsa.rsa_p = sk.p;
     skc->d.rsa.rsa_q = sk.q;
     skc->d.rsa.rsa_u = sk.u;
-    skc->d.rsa.calc_csum = 0;
-    skc->d.rsa.is_protected = 0; /* FIXME!!! */
-    skc->d.rsa.protect_algo = 0; /* should be blowfish */
-    /*memcpy(skc->d.rsa.protect.blowfish.iv,"12345678", 8);*/
+    skc->d.rsa.csum  = checksum_mpi( skc->d.rsa.rsa_d );
+    skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_p );
+    skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q );
+    skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u );
+    if( !dek ) {
+       skc->d.rsa.is_protected = 0;
+       skc->d.rsa.protect_algo = 0;
+    }
+    else {
+       skc->d.rsa.is_protected = 1;
+       skc->d.rsa.protect_algo = CIPHER_ALGO_BLOWFISH;
+       randomize_buffer( skc->d.rsa.protect.blowfish.iv, 8, 1);
+       skc->d.rsa.csum += checksum( skc->d.rsa.protect.blowfish.iv, 8 );
+       rc = protect_secret_key( skc, dek );
+       if( rc ) {
+           log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
+           goto leave;
+       }
+    }
 
-    init_packet(&pkt1);
     pkt1.pkttype = PKT_PUBLIC_CERT;
     pkt1.pkt.public_cert = pkc;
-    init_packet(&pkt2);
     pkt2.pkttype = PKT_SECRET_CERT;
     pkt2.pkt.secret_cert = skc;
 
@@ -116,6 +198,10 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
        log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
        goto leave;
     }
+    *ret_pkc = pkt1.pkt.public_cert;
+    pkt1.pkt.public_cert = NULL;
+    *ret_skc = pkt1.pkt.secret_cert;
+    pkt1.pkt.secret_cert = NULL;
 
   leave:
     free_packet(&pkt1);
@@ -125,14 +211,19 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
 #endif /*HAVE_RSA_CIPHER*/
 
 static int
-gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
+gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
+       PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
 {
     int rc;
     PACKET pkt1, pkt2;
-    PKT_secret_cert *skc;
+    PKT_secret_cert *skc, *unprotected_skc;
     PKT_public_cert *pkc;
     ELG_public_key pk;
     ELG_secret_key sk;
+    unsigned nbytes;
+
+    init_packet(&pkt1);
+    init_packet(&pkt2);
 
     elg_generate( &pk, &sk, nbits );
 
@@ -150,15 +241,25 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
     skc->d.elg.y = sk.y;
     skc->d.elg.x = sk.x;
 
-    skc->d.elg.calc_csum = 0;
-    skc->d.elg.is_protected = 0; /* FIXME!!! */
-    skc->d.elg.protect_algo = 0; /* should be blowfish */
-    /*memcpy(skc->d.elg.protect.blowfish.iv,"12345678", 8);*/
+    skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
+    unprotected_skc = copy_secret_cert( NULL, skc );
+    if( !dek ) {
+       skc->d.elg.is_protected = 0;
+       skc->d.elg.protect_algo = 0;
+    }
+    else {
+       skc->d.elg.is_protected = 0;
+       skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
+       randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
+       rc = protect_secret_key( skc, dek );
+       if( rc ) {
+           log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
+           goto leave;
+       }
+    }
 
-    init_packet(&pkt1);
     pkt1.pkttype = PKT_PUBLIC_CERT;
     pkt1.pkt.public_cert = pkc;
-    init_packet(&pkt2);
     pkt2.pkttype = PKT_SECRET_CERT;
     pkt2.pkt.secret_cert = skc;
 
@@ -170,10 +271,17 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
        log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
        goto leave;
     }
+    *ret_pkc = pkt1.pkt.public_cert;
+    pkt1.pkt.public_cert = NULL;
+    *ret_skc = unprotected_skc;
+    unprotected_skc = NULL;
+
 
   leave:
     free_packet(&pkt1);
     free_packet(&pkt2);
+    if( unprotected_skc )
+       free_secret_cert( unprotected_skc );
     return rc;
 }
 
@@ -192,6 +300,10 @@ generate_keypair()
     char *uid = NULL;
     IOBUF pub_io = NULL;
     IOBUF sec_io = NULL;
+    PKT_public_cert *pkc = NULL;
+    PKT_secret_cert *skc = NULL;
+    PKT_user_id *upkt = NULL;
+    DEK *dek = NULL;
     int rc;
     int algo;
     const char *algo_name;
@@ -301,6 +413,28 @@ generate_keypair()
        }
     }
   #endif
+
+
+    tty_printf( "You need a Passphrase to protect your secret key.\n\n" );
+
+    dek = m_alloc_secure( sizeof *dek );
+    dek->algo = CIPHER_ALGO_BLOWFISH;
+    rc = make_dek_from_passphrase( dek , 2 );
+    if( rc == -1 ) {
+       m_free(dek); dek = NULL;
+       tty_printf(
+           "You don't what a passphrase - this is probably a *bad* idea!\n"
+           "I will do it anyway.  You can change your passphrase at anytime,\n"
+           "using this program with the option \"--change-passphrase\"\n\n" );
+    }
+    else if( rc ) {
+       m_free(dek); dek = NULL;
+       m_free(uid);
+       log_error("Error getting the passphrase: %s\n", g10_errstr(rc) );
+       return;
+    }
+
+
     /* now check wether we a are allowed to write the keyrings */
     if( !(rc=overwrite_filep( pub_fname )) ) {
        if( !(pub_io = iobuf_create( pub_fname )) )
@@ -334,23 +468,41 @@ generate_keypair()
        return;
     }
 
-
     write_comment( pub_io, "#public key created by G10 pre-release " VERSION );
     write_comment( sec_io, "#secret key created by G10 pre-release " VERSION );
 
     if( algo == PUBKEY_ALGO_ELGAMAL )
-       gen_elg(nbits, pub_io, sec_io);
+       rc = gen_elg(nbits, pub_io, sec_io, dek, &pkc, &skc);
   #ifdef HAVE_RSA_CIPHER
     else if( algo == PUBKEY_ALGO_RSA )
-       gen_rsa(nbits, pub_io, sec_io);
+       rc = gen_rsa(nbits, pub_io, sec_io, dek, &pkc, &skc);
   #endif
     else
        log_bug(NULL);
-    write_uid(pub_io, uid );
-    write_uid(sec_io, uid );
+    if( !rc )
+       write_uid(pub_io, uid, &upkt );
+    if( !rc )
+       write_uid(sec_io, uid, NULL );
+    if( !rc )
+       rc = write_selfsig(pub_io, pkc, upkt, skc );
+
+    if( rc ) {
+       iobuf_cancel(pub_io);
+       iobuf_cancel(sec_io);
+       tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
+    }
+    else {
+       iobuf_close(pub_io);
+       iobuf_close(sec_io);
+       tty_printf("public and secret key created and signed.\n" );
+    }
+    if( pkc )
+       free_public_cert( pkc );
+    if( skc )
+       free_secret_cert( skc );
+    if( upkt )
+       free_user_id( upkt );
     m_free(uid);
-
-    iobuf_close(pub_io);
-    iobuf_close(sec_io);
+    m_free(dek);
 }
 
index 7453754..e3a16d8 100644 (file)
@@ -171,3 +171,110 @@ datestr_from_sig( PKT_signature *sig )
     return buffer;
 }
 
+
+/**************** .
+ * Return a byte array with the fingerprint for the given PKC/SKC
+ * The length of the array is returned in ret_len. Caller must free
+ * the array.
+ */
+byte *
+fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
+{
+    PKT_public_cert pkc;
+    byte *p;
+
+    pkc.pubkey_algo = skc->pubkey_algo;
+    if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       pkc.timestamp = skc->timestamp;
+       pkc.valid_days = skc->valid_days;
+       pkc.pubkey_algo = skc->pubkey_algo;
+       pkc.d.elg.p = skc->d.elg.p;
+       pkc.d.elg.g = skc->d.elg.g;
+       pkc.d.elg.y = skc->d.elg.y;
+    }
+    else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
+       pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
+       pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
+    }
+    p = fingerprint_from_pkc( &pkc, ret_len );
+    memset(&pkc, 0, sizeof pkc); /* not really needed */
+    return p;
+}
+
+byte *
+fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
+{
+    byte *p, *buf, *array;
+    size_t len;
+    unsigned n;
+
+    if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       RMDHANDLE md;
+       const char *dp;
+
+       md = rmd160_open(0);
+
+       {   u32 a = pkc->timestamp;
+           rmd160_putchar( md, a >> 24 );
+           rmd160_putchar( md, a >> 16 );
+           rmd160_putchar( md, a >>  8 );
+           rmd160_putchar( md, a       );
+       }
+       {   u16 a = pkc->valid_days;
+           rmd160_putchar( md, a >> 8 );
+           rmd160_putchar( md, a      );
+       }
+       rmd160_putchar( md, pkc->pubkey_algo );
+       p = buf = mpi_get_buffer( pkc->d.elg.p, &n, NULL );
+       for( ; !*p && n; p++, n-- )
+           ;
+       rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
+       m_free(buf);
+       p = buf = mpi_get_buffer( pkc->d.elg.g, &n, NULL );
+       for( ; !*p && n; p++, n-- )
+           ;
+       rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
+       m_free(buf);
+       p = buf = mpi_get_buffer( pkc->d.elg.y, &n, NULL );
+       for( ; !*p && n; p++, n-- )
+           ;
+       rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
+       m_free(buf);
+
+       dp = rmd160_final(md);
+       array = m_alloc( 20 );
+       len = 20;
+       memcpy(array, dp, 20 );
+       rmd160_close(md);
+    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       MD5HANDLE md;
+
+       md = md5_open(0);
+       p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL );
+       for( ; !*p && n; p++, n-- )
+           ;
+       md5_write( md, p, n );
+       m_free(buf);
+       p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL );
+       for( ; !*p && n; p++, n-- )
+           ;
+       md5_write( md, p, n );
+       m_free(buf);
+       md5_final(md);
+       array = m_alloc( 16 );
+       len = 16;
+       memcpy(array, md5_read(md), 16 );
+       md5_close(md);
+    }
+    else {
+       array = m_alloc(1);
+       len = 0; /* ooops */
+    }
+
+    *ret_len = len;
+    return array;
+}
+
+
+
index 9418da4..a04b0fc 100644 (file)
@@ -342,7 +342,7 @@ proc_plaintext( CTX c, PACKET *pkt )
     printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
     free_md_filter_context( &c->mfx );
     /* fixme: take the digest algo to use from the
-     * onpass_sig packet (if we have these) */
+     * onepass_sig packet (if we have these) */
     c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
     result = handle_plaintext( pt, &c->mfx );
     if( !result )
@@ -450,6 +450,34 @@ print_userid( PACKET *pkt )
 }
 
 
+static void
+print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
+{
+    byte *array, *p;
+    size_t i, n;
+
+    p = array = skc? fingerprint_from_skc( skc, &n )
+                  : fingerprint_from_pkc( pkc, &n );
+    printf("     Key fingerprint =");
+    if( n == 20 ) {
+       for(i=0; i < n ; i++, i++, p += 2 ) {
+           if( i == 10 )
+               putchar(' ');
+           printf(" %02X%02X", *p, p[1] );
+       }
+    }
+    else {
+       for(i=0; i < n ; i++, p++ ) {
+           if( i && !(i%8) )
+               putchar(' ');
+           printf(" %02X", *p );
+       }
+    }
+    putchar('\n');
+    m_free(array);
+}
+
+
 /****************
  * List the certificate in a user friendly way
  */
@@ -478,6 +506,8 @@ list_node( CTX c, NODE node )
                    printf( "%*s", 31, "" );
                print_userid( n2->pkt );
                putchar('\n');
+               if( opt.fingerprint && n2 == node->child )
+                   print_fingerprint( pkc, NULL );
                list_node(c,  n2 );
            }
        }
@@ -491,18 +521,20 @@ list_node( CTX c, NODE node )
                                      datestr_from_skc( skc )     );
        n2 = node->child;
        if( !n2 )
-           printf("ERROR: no user id!");
+           printf("ERROR: no user id!\n");
        else {
            print_userid( n2->pkt );
+           putchar('\n');
+           if( opt.fingerprint && n2 == node->child )
+               print_fingerprint( NULL, skc );
        }
-       putchar('\n');
     }
     else if( node->pkt->pkttype == PKT_USER_ID ) {
        /* list everything under this user id */
        for(n2=node->child; n2; n2 = n2->next )
            list_node(c,  n2 );
     }
-    else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+    else if( node->pkt->pkttype == PKT_SIGNATURE  ) {
        PKT_signature *sig = node->pkt->pkt.signature;
        int rc2;
        size_t n;
@@ -510,6 +542,9 @@ list_node( CTX c, NODE node )
        int sigrc = ' ';
 
        assert( !node->child );
+       if( !opt.list_sigs )
+           return;
+
        if( opt.check_sigs ) {
 
            switch( (rc2=do_check_sig( c, node )) ) {
index 2b65db2..a23412f 100644 (file)
@@ -32,8 +32,8 @@ struct {
     int answer_no;  /* answer no on most questions */
     int check_sigs; /* check key signatures */
     int cache_all;
-    int detached_sig;
-    int reserved3;
+    int fingerprint; /* list fingerprints */
+    int list_sigs;   /* list signatures */
     int reserved4;
     int reserved5;
     int reserved6;
index 5694c8a..57adebe 100644 (file)
@@ -124,7 +124,6 @@ typedef struct {
        MPI rsa_q;          /* secret second prime number */
        MPI rsa_u;          /* secret multiplicative inverse */
        u16 csum;           /* checksum */
-       u16 calc_csum;      /* and a place to store the calculated csum */
        byte is_protected;  /* The above infos are protected and must */
                            /* be decrypteded before use */
        byte protect_algo;  /* cipher used to protect the secret informations*/
@@ -142,7 +141,6 @@ typedef struct {
        MPI y;              /* g^x mod p */
        MPI x;              /* secret exponent */
        u16 csum;           /* checksum */
-       u16 calc_csum;      /* and a place to store the calculated csum */
        byte is_protected;  /* The above infos are protected and must */
                            /* be decrypteded before use */
        byte protect_algo;  /* cipher used to protect the secret informations*/
@@ -220,6 +218,7 @@ int parse_packet( IOBUF inp, PACKET *ret_pkt);
 /*-- build-packet.c --*/
 int build_packet( IOBUF inp, PACKET *pkt );
 u32 calc_packet_length( PACKET *pkt );
+void hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc );
 
 /*-- free-packet.c --*/
 void free_pubkey_enc( PKT_pubkey_enc *enc );
@@ -238,6 +237,7 @@ int signature_check( PKT_signature *sig, MD_HANDLE *digest );
 
 /*-- seckey-cert.c --*/
 int check_secret_key( PKT_secret_cert *cert );
+int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
 
 /*-- pubkey-enc.c --*/
 int get_session_key( PKT_pubkey_enc *k, DEK *dek );
@@ -256,5 +256,9 @@ int ask_for_detached_datafile( md_filter_context_t *mfx );
 /*-- comment.c --*/
 int write_comment( IOBUF out, const char *s );
 
+/*-- sign.c --*/
+int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
+                       PKT_user_id *uid, PKT_secret_cert *skc,
+                       int sigclass, int digest_algo );
 
 #endif /*G10_PACKET_H*/
index 6aef1b4..5badb0e 100644 (file)
@@ -239,8 +239,8 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
                                        k->keyid[0], k->keyid[1]);
     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        n = pktlen;
-       k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
-       k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
+       k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
+       k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf("\telg a: ");
            mpi_print(stdout, k->d.elg.a, mpi_print_mode );
@@ -251,7 +251,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     }
     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
        n = pktlen;
-       k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
+       k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf("\trsa integer: ");
            mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
@@ -304,8 +304,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
        sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
        n = pktlen;
-       sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
-       sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
+       sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
+       sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf("\tdigest algo %d, begin of digest %02x %02x\n",
                    sig->d.elg.digest_algo,
@@ -313,7 +313,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
            printf("\telg a: ");
            mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
            printf("\n\telg b: ");
-           mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
+           mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
            putchar('\n');
        }
     }
@@ -326,7 +326,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
        sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
        n = pktlen;
-       sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
+       sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf("\tdigest algo %d, begin of digest %02x %02x\n",
                    sig->d.rsa.digest_algo,
@@ -439,9 +439,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
 
     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
        MPI elg_p, elg_g, elg_y;
-       n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n;
-       n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n;
-       n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n;
+       n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
+       n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
+       n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf(  "\telg p:  ");
            mpi_print(stdout, elg_p, mpi_print_mode  );
@@ -483,32 +483,24 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
            else
                cert->d.elg.is_protected = 0;
 
-           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
-           cert->d.elg.x = (MPI)mpibuf;
+           n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
 
            cert->d.elg.csum = read_16(inp); pktlen -= 2;
-           cert->d.elg.calc_csum = 0;
            if( list_mode ) {
                printf("\t[secret value x is not shown]\n"
                       "\tchecksum: %04hx\n", cert->d.elg.csum);
            }
-           if( !cert->d.elg.is_protected ) { /* convert buffer to MPIs */
-               mpibuf = (byte*)cert->d.elg.x;
-               cert->d.elg.calc_csum += checksum( mpibuf );
-               cert->d.elg.x = mpi_decode_buffer( mpibuf );
-               m_free( mpibuf );
-             /*log_mpidump("elg p=", cert->d.elg.p );
-               log_mpidump("elg g=", cert->d.elg.g );
-               log_mpidump("elg y=", cert->d.elg.y );
-               log_mpidump("elg x=", cert->d.elg.x ); */
-           }
+         /*log_mpidump("elg p=", cert->d.elg.p );
+           log_mpidump("elg g=", cert->d.elg.g );
+           log_mpidump("elg y=", cert->d.elg.y );
+           log_mpidump("elg x=", cert->d.elg.x ); */
        }
     }
     else if( algorithm == PUBKEY_ALGO_RSA ) {
        MPI rsa_pub_mod, rsa_pub_exp;
 
-       n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
-       n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
+       n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
+       n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
            printf(  "\tpublic modulus  n:  ");
            mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
@@ -546,43 +538,22 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
            else
                cert->d.rsa.is_protected = 0;
 
-           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
-           cert->d.rsa.rsa_d = (MPI)mpibuf;
-
-           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
-           cert->d.rsa.rsa_p = (MPI)mpibuf;
-
-           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
-           cert->d.rsa.rsa_q = (MPI)mpibuf;
-
-           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
-           cert->d.rsa.rsa_u = (MPI)mpibuf;
+           n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
+           n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 1 ); pktlen -=n;
+           n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 1 ); pktlen -=n;
+           n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
 
            cert->d.rsa.csum = read_16(inp); pktlen -= 2;
-           cert->d.rsa.calc_csum = 0;
            if( list_mode ) {
                printf("\t[secret values d,p,q,u are not shown]\n"
                       "\tchecksum: %04hx\n", cert->d.rsa.csum);
            }
-           if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */
-             #define X(a) do {                                         \
-                   mpibuf = (byte*)cert->d.rsa.rsa_##a;                \
-                   cert->d.rsa.calc_csum += checksum( mpibuf );        \
-                   cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf );  \
-                   m_free( mpibuf );                                   \
-               } while(0)
-               X(d);
-               X(p);
-               X(q);
-               X(u);
-             #undef X
-            /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
-               log_mpidump("rsa e=", cert->d.rsa.rsa_e );
-               log_mpidump("rsa d=", cert->d.rsa.rsa_d );
-               log_mpidump("rsa p=", cert->d.rsa.rsa_p );
-               log_mpidump("rsa q=", cert->d.rsa.rsa_q );
-               log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
-           }
+        /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
+           log_mpidump("rsa e=", cert->d.rsa.rsa_e );
+           log_mpidump("rsa d=", cert->d.rsa.rsa_d );
+           log_mpidump("rsa p=", cert->d.rsa.rsa_p );
+           log_mpidump("rsa q=", cert->d.rsa.rsa_q );
+           log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
        }
     }
     else if( list_mode )
@@ -671,34 +642,9 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
        1 = "we do not trust this key's ownership"
        2 = "we have marginal confidence of this key's ownership"
        3 = "we completely trust this key's ownership."
-        /* This one (3) requires either:
-         * - 1 ultimately trusted signature (SIGTRUST=7)
-         * - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6)
-         * - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5)
-         */
        if( c & 0x80 )
            "warnonly"
     else if( prev_packet_is_a_signature ) {
-        Bits 0-2 - SIGTRUST bits - Trust bits for this signature.  Value is
-                   copied directly from OWNERTRUST bits of signer:
-             000 - undefined, or uninitialized trust.
-             001 - unknown
-             010 - We do not trust this signature.
-             011 - reserved
-             100 - reserved
-             101 - We reasonably trust this signature.
-             110 - We completely trust this signature.
-             111 - ultimately trusted signature (from the owner of the ring)
-         Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc,
-                 also invoked automatically whenever keys are added to the
-                 keyring) has tested this signature and found it good.  If
-                 this bit is not set, the maintenance pass considers this
-                 signature untrustworthy.
-         Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted
-                 certification path all the way back to the ultimately-
-                 trusted keyring owner, where the buck stops.  This bit is derived
-                 from other trust packets.  It is currently not used for anything
-                 in PGP.
     }
   #endif
 }
index 5a45f49..4e5e57b 100644 (file)
@@ -44,13 +44,13 @@ get_passphrase_hash( u32 *keyid, char *text )
     DEK *dek;
 
     if( keyid ) {
-       tty_printf("Need a pass phrase to unlock the secret key!\n");
+       tty_printf("\nNeed a pass phrase to unlock the secret key!\n");
        tty_printf("KeyID: %08lX\n\n",  keyid[1] );
     }
-    if( keyid && (p=getenv("PGPPATHPHRASE")) ) {
+    if( keyid && (p=getenv("G10PASSPHRASE")) ) {
        pw = m_alloc_secure(strlen(p)+1);
        strcpy(pw,p);
-       tty_printf("Taking it from $PGPPATHPHRASE !\n",  keyid[1] );
+       tty_printf("Taking it from $G10PASSPHRASE !\n",  keyid[1] );
     }
     else
        pw = tty_get_hidden("Enter pass phrase: " );
@@ -61,7 +61,7 @@ get_passphrase_hash( u32 *keyid, char *text )
     m_free(pw); /* is allocated in secure memory, so it will be burned */
     if( !p ) {
        tty_kill_prompt();
-       tty_printf("\n\n");
+       tty_printf("\n");
     }
     return dek;
 }
@@ -70,6 +70,7 @@ get_passphrase_hash( u32 *keyid, char *text )
 /****************
  * This function is used to construct a DEK from a user input.
  * It uses the default CIPHER
+ * Returns: 0 = okay, -1 No passphrase entered, > 0 error
  */
 int
 make_dek_from_passphrase( DEK *dek, int mode )
@@ -88,7 +89,10 @@ make_dek_from_passphrase( DEK *dek, int mode )
        }
        m_free(pw2);
     }
-    rc = hash_passphrase( dek, pw );
+    if( !*pw )
+       rc = -1;
+    else
+       rc = hash_passphrase( dek, pw );
     m_free(pw);
     return rc;
 }
index 689f473..85d93b4 100644 (file)
 #endif
 
 static u16
-checksum( byte *p )
+checksum_u16( unsigned n )
 {
-    u16 n, a;
+    u16 a;
+
+    a  = (n >> 8) & 0xff;
+    a |= n & 0xff;
+    return a;
+}
+
+static u16
+checksum( byte *p, unsigned n )
+{
+    u16 a;
 
-    n = *p++ << 8;
-    n |= *p++;
     for(a=0; n; n-- )
        a += *p++;
     return a;
@@ -51,16 +59,16 @@ checksum( byte *p )
 static int
 check_elg( PKT_secret_cert *cert )
 {
-    byte iv[8];
-    byte *mpibuf;
-    u16 n;
-    MPI temp_mpi;
+    byte *buffer;
+    u16 n, csum=0;
     int res;
+    unsigned nbytes;
     u32 keyid[2];
     ELG_secret_key skey;
 
     if( cert->d.elg.is_protected ) { /* remove the protection */
        DEK *dek = NULL;
+       MPI test_x;
        BLOWFISH_context *blowfish_ctx=NULL;
 
        switch( cert->d.elg.protect_algo ) {
@@ -68,47 +76,87 @@ check_elg( PKT_secret_cert *cert )
          case CIPHER_ALGO_BLOWFISH:
            keyid_from_skc( cert, keyid );
            dek = get_passphrase_hash( keyid, NULL );
-           m_free(dek); /* pw is in secure memory, so m_free() burns it */
-           memset( iv, 0, BLOWFISH_BLOCKSIZE );
            blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
-           blowfish_setiv( blowfish_ctx, iv );
+           blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+           m_free(dek); /* pw is in secure memory, so m_free() burns it */
+           blowfish_setiv( blowfish_ctx, NULL );
            blowfish_decode_cfb( blowfish_ctx,
                                 cert->d.elg.protect.blowfish.iv,
                                 cert->d.elg.protect.blowfish.iv, 8 );
-           cert->d.elg.calc_csum = 0;
-           mpibuf = (byte*)cert->d.elg.x;
-           n = ((mpibuf[0] << 8) | mpibuf[1])-2;
-           blowfish_decode_cfb( blowfish_ctx, mpibuf+4, mpibuf+4, n );
-           cert->d.elg.calc_csum += checksum( mpibuf );
-           cert->d.elg.x = mpi_decode_buffer( mpibuf );
-           m_free( mpibuf );
+           buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
+           csum = checksum_u16( nbytes*8 );
+           blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           csum += checksum( buffer, nbytes );
+           test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
+           mpi_set_buffer( test_x, buffer, nbytes, 0 );
+           m_free( buffer );
            m_free( blowfish_ctx );
-           cert->d.elg.is_protected = 0;
            /* now let's see wether we have used the right passphrase */
-           if( cert->d.elg.calc_csum != cert->d.elg.csum )
+           if( csum != cert->d.elg.csum ) {
+               mpi_free(test_x);
                return G10ERR_BAD_PASS;
+           }
 
            skey.p = cert->d.elg.p;
            skey.g = cert->d.elg.g;
            skey.y = cert->d.elg.y;
-           skey.x = cert->d.elg.x;
+           skey.x = test_x;
            res = elg_check_secret_key( &skey );
            memset( &skey, 0, sizeof skey );
-           if( !res )
+           if( !res ) {
+               mpi_free(test_x);
                return G10ERR_BAD_PASS;
+           }
+           mpi_set(cert->d.elg.x, test_x);
+           mpi_free(test_x);
+           cert->d.elg.is_protected = 0;
            break;
 
          default:
            return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
        }
     }
-    /* must check the checksum here, because we didn't do it when
-     * parsing an unprotected certificate */
-    if( cert->d.elg.calc_csum != cert->d.elg.csum ) {
-       log_error("checksum in secret key certificate is wrong\n");
-       log_debug("stored csum=%04hx calculated csum=%04hx\n",
-                  cert->d.elg.csum, cert->d.elg.calc_csum );
-       return G10ERR_CHECKSUM;
+    else { /* not protected */
+       buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
+       csum = checksum_u16( nbytes*8 );
+       csum += checksum( buffer, nbytes );
+       m_free( buffer );
+       if( csum != cert->d.elg.csum )
+           return G10ERR_CHECKSUM;
+    }
+
+    return 0;
+}
+
+static int
+protect_elg( PKT_secret_cert *cert, DEK *dek )
+{
+    byte *buffer;
+    unsigned nbytes;
+
+    if( !cert->d.elg.is_protected ) { /* add the protection */
+       BLOWFISH_context *blowfish_ctx=NULL;
+
+       switch( cert->d.elg.protect_algo ) {
+         case CIPHER_ALGO_NONE: log_bug(NULL); break;
+         case CIPHER_ALGO_BLOWFISH:
+           blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+           blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+           blowfish_setiv( blowfish_ctx, NULL );
+           blowfish_encode_cfb( blowfish_ctx,
+                                cert->d.elg.protect.blowfish.iv,
+                                cert->d.elg.protect.blowfish.iv, 8 );
+           buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
+           blowfish_encode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 );
+           m_free( buffer );
+           m_free( blowfish_ctx );
+           cert->d.elg.is_protected = 1;
+           break;
+
+         default:
+           return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
+       }
     }
     return 0;
 }
@@ -118,80 +166,86 @@ check_elg( PKT_secret_cert *cert )
 static int
 check_rsa( PKT_secret_cert *cert )
 {
-    byte iv[8];
-    byte *mpibuf;
-    u16 n;
-    MPI temp_mpi;
+    byte *buffer;
+    u16 n, csum=0;
     int res;
+    unsigned nbytes;
     u32 keyid[2];
+    RSA_secret_key skey;
 
     if( cert->d.rsa.is_protected ) { /* remove the protection */
        DEK *dek = NULL;
        BLOWFISH_context *blowfish_ctx=NULL;
 
        switch( cert->d.rsa.protect_algo ) {
-         case CIPHER_ALGO_NONE:
-           log_bug("unprotect secret_cert is flagged protected\n");
-           break;
+           /* FIXME: use test variables to check for the correct key */
+         case CIPHER_ALGO_NONE: log_bug(NULL); break;
          case CIPHER_ALGO_BLOWFISH:
            keyid_from_skc( cert, keyid );
            dek = get_passphrase_hash( keyid, NULL );
-
-           m_free(dek); /* pw is in secure memory, so m_free() burns it */
-           memset( iv, 0, BLOWFISH_BLOCKSIZE );
            blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
-           blowfish_setiv( blowfish_ctx, iv );
+           blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+           m_free(dek); /* pw is in secure memory, so m_free() burns it */
+           blowfish_setiv( blowfish_ctx, NULL );
            blowfish_decode_cfb( blowfish_ctx,
                                 cert->d.rsa.protect.blowfish.iv,
                                 cert->d.rsa.protect.blowfish.iv, 8 );
-           cert->d.rsa.calc_csum = 0;
-         #define X(a) do {                                             \
-                   mpibuf = (byte*)cert->d.rsa.rsa_##a;                \
-                   n = ((mpibuf[0] << 8) | mpibuf[1])-2;               \
-                   blowfish_decode_cfb( blowfish_ctx,                  \
-                                        mpibuf+4, mpibuf+4, n );       \
-                   cert->d.rsa.calc_csum += checksum( mpibuf );        \
-                   cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf );  \
-                   m_free( mpibuf );                                   \
-               } while(0)
+           csum = 0;
+           #define X(a) do { \
+               buffer = mpi_get_buffer( cert->d.rsa.rsa_##a, &nbytes, NULL );\
+               csum += checksum_u16( nbytes*8 );                            \
+               blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); \
+               csum += checksum( buffer, nbytes );                          \
+               mpi_set_buffer(cert->d.rsa.rsa_##a, buffer, nbytes, 0 );     \
+               m_free( buffer );                                            \
+              } while(0)
            X(d);
            X(p);
            X(q);
            X(u);
-         #undef X
-           m_free( blowfish_ctx );
-           cert->d.rsa.is_protected = 0;
-         #if 0
-           #define X(a) do { printf("\tRSA " #a ": ");                   \
-                             mpi_print(stdout, cert->d.rsa.rsa_##a, 1 ); \
-                             putchar('\n');                              \
-                           } while(0)
-           X(n); X(e); X(d); X(p); X(q); X(u);
            #undef X
-         #endif
+           cert->d.rsa.is_protected = 0;
+           m_free( blowfish_ctx );
            /* now let's see wether we have used the right passphrase */
-           if( cert->d.rsa.calc_csum != cert->d.rsa.csum )
+           if( csum != cert->d.rsa.csum )
                return G10ERR_BAD_PASS;
-           temp_mpi = mpi_alloc(40);
-           mpi_mul(temp_mpi, cert->d.rsa.rsa_p, cert->d.rsa.rsa_q );
-           res = mpi_cmp( temp_mpi, cert->d.rsa.rsa_n );
-           mpi_free(temp_mpi);
-           if( res )
+
+           skey.d = cert->d.rsa.rsa_d;
+           skey.p = cert->d.rsa.rsa_p;
+           skey.q = cert->d.rsa.rsa_q;
+           skey.u = cert->d.rsa.rsa_u;
+           res = rsa_check_secret_key( &skey );
+           memset( &skey, 0, sizeof skey );
+           if( !res )
                return G10ERR_BAD_PASS;
            break;
 
          default:
-           return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
+           return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
        }
     }
-    /* must check the checksum here, because we didn't do it when
-     * parsing an unprotected certificate */
-    if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) {
-       log_error("checksum in secret key certificate is wrong\n");
-       log_debug("stored csum=%04hx calculated csum=%04hx\n",
-                  cert->d.rsa.csum, cert->d.rsa.calc_csum );
-       return G10ERR_CHECKSUM;
+    else { /* not protected */
+       csum =0;
+       buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL );
+       csum += checksum_u16( nbytes*8 );
+       csum += checksum( buffer, nbytes );
+       m_free( buffer );
+       buffer = mpi_get_buffer( cert->d.rsa.rsa_p, &nbytes, NULL );
+       csum += checksum_u16( nbytes*8 );
+       csum += checksum( buffer, nbytes );
+       m_free( buffer );
+       buffer = mpi_get_buffer( cert->d.rsa.rsa_q, &nbytes, NULL );
+       csum += checksum_u16( nbytes*8 );
+       csum += checksum( buffer, nbytes );
+       m_free( buffer );
+       buffer = mpi_get_buffer( cert->d.rsa.rsa_u, &nbytes, NULL );
+       csum += checksum_u16( nbytes*8 );
+       csum += checksum( buffer, nbytes );
+       m_free( buffer );
+       if( csum != cert->d.rsa.csum )
+           return G10ERR_CHECKSUM;
     }
+
     return 0;
 }
 #endif /*HAVE_RSA_CIPHER*/
@@ -201,15 +255,44 @@ check_rsa( PKT_secret_cert *cert )
 
 /****************
  * Check the secret key certificate
+ * Ask up to 3 time for a correct passphrase
  */
 int
 check_secret_key( PKT_secret_cert *cert )
 {
+    int rc = G10ERR_BAD_PASS;
+    int i;
+
+    for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
+       if( i )
+           log_error("Invalid passphrase; please try again ...\n");
+       if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
+           rc = check_elg( cert );
+      #ifdef HAVE_RSA_CIPHER
+       else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
+           rc = check_rsa( cert );
+      #endif
+       else
+           rc = G10ERR_PUBKEY_ALGO;
+    }
+    return rc;
+}
+
+
+/****************
+ * Protect the secret key certificate with the passphrase from DEK
+ */
+int
+protect_secret_key( PKT_secret_cert *cert, DEK *dek )
+{
+    if( !dek )
+       return 0;
+
     if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
-       return check_elg( cert );
-  #ifdef HAVE_RSA_CIPHER
+       return protect_elg( cert, dek );
+  #ifdef 0 /* noy yet implemented */
     else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
-       return check_rsa( cert );
+       return protect_rsa( cert, dek );
   #endif
     else
        return G10ERR_PUBKEY_ALGO;
index 8414238..d5f0afb 100644 (file)
@@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
     return rc;
 }
 
+
+
index 7ad3181..cdd4a05 100644 (file)
@@ -49,5 +49,6 @@
 #define G10ERR_NI_PUBKEY      27
 #define G10ERR_NI_CIPHER      28
 #define G10ERR_SIG_CLASS      29
+#define G10ERR_BAD_MPI       30
 
 #endif /*G10_ERRORS_H*/
index aa8bb70..32eb390 100644 (file)
@@ -33,6 +33,7 @@
 #define m_realloc(n,m)         m_debug_realloc((n),(m), M_DBGINFO(__LINE__) )
 #define m_free(n)              m_debug_free((n), M_DBGINFO(__LINE__) )
 #define m_check(n)             m_debug_check((n), M_DBGINFO(__LINE__) )
+#define m_copy(a)              m_debug_copy((a), M_DBGINFO(__LINE__) )
 
 void *m_debug_alloc( size_t n, const char *info );
 void *m_debug_alloc_clear( size_t n, const char *info  );
@@ -41,6 +42,7 @@ void *m_debug_alloc_secure_clear( size_t n, const char *info  );
 void *m_debug_realloc( void *a, size_t n, const char *info  );
 void m_debug_free( void *p, const char *info  );
 void m_debug_check( const void *a, const char *info );
+void *m_debug_copy( const void *a, const char *info );
 
 #else
 void *m_alloc( size_t n );
@@ -50,6 +52,7 @@ void *m_alloc_secure_clear( size_t n );
 void *m_realloc( void *a, size_t n );
 void m_free( void *p );
 void m_check( const void *a );
+void *m_copy( void *a );
 #endif
 
 
index cf36232..ce60f16 100644 (file)
@@ -52,15 +52,16 @@ int mpi_debug_mode;
 typedef struct mpi_struct {
     int alloced;    /* array size (# of allocated limbs) */
     int nlimbs;     /* number of valid limbs */
+    int nbits;     /* the real number of valid bits (info only) */
     int sign;      /* indicates a negative number */
-    int secure;     /* array mut be allocated in secure memory space */
+    int secure;     /* array must be allocated in secure memory space */
     mpi_limb_t *d;  /* array with the limbs */
 } *MPI;
 
 #define MPI_NULL NULL
 
-#define mpi_get_nlimbs(a) ((a)->nlimbs)
-#define mpi_is_neg(a)    ((a)->sign)
+#define mpi_get_nlimbs(a)     ((a)->nlimbs)
+#define mpi_is_neg(a)        ((a)->sign)
 
 /*-- mpiutil.c --*/
 
@@ -90,23 +91,18 @@ void mpi_m_check( MPI a );
 void mpi_swap( MPI a, MPI b);
 
 /*-- mpicoder.c --*/
-int mpi_encode( IOBUF out, MPI a );
-int mpi_encode_csum( IOBUF out, MPI a, u16 *csum );
-int mpi_write( IOBUF out, byte *a);
-int mpi_write_csum( IOBUF out, byte *a, u16 *csum);
+int mpi_write( IOBUF out, MPI a );
 #ifdef M_DEBUG
-  #define mpi_decode(a,b)   mpi_debug_decode((a),(b),  M_DBGINFO( __LINE__ ) )
-  #define mpi_decode_buffer(a)  mpi_debug_decode_buffer((a), M_DBGINFO( __LINE__ ) )
-  MPI mpi_debug_decode(IOBUF inp, unsigned *nread, const char *info);
-  MPI mpi_debug_decode_buffer(byte *buffer, const char *info );
+  #define mpi_read(a,b,c)   mpi_debug_read((a),(b),(c),  M_DBGINFO( __LINE__ ) )
+  MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info);
 #else
-  MPI mpi_decode(IOBUF inp, unsigned *nread);
-  MPI mpi_decode_buffer(byte *buffer );
+  MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
 #endif
-byte *mpi_read(IOBUF inp, unsigned *ret_nread);
 int mpi_fromstr(MPI val, const char *str);
 int mpi_print( FILE *fp, MPI a, int mode );
 u32 mpi_get_keyid( MPI a, u32 *keyid );
+byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
+void  mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign );
 
 /*-- mpi-add.c --*/
 void mpi_add_ui(MPI w, MPI u, ulong v );
index 23454c0..43b97be 100644 (file)
 #include <assert.h>
 
 #include "mpi.h"
+#include "mpi-internal.h"
 #include "iobuf.h"
 #include "memory.h"
 #include "util.h"
 
 #ifdef M_DEBUG
-  #undef mpi_decode
-  #undef mpi_decode_buffer
+  #undef mpi_read
 #endif
 
 #define MAX_EXTERN_MPI_BITS 16384
  * write an mpi to out.
  */
 int
-mpi_encode( IOBUF out, MPI a )
-{
-    u16 dummy;
-    return mpi_encode_csum( out, a, &dummy );
-}
-
-int
-mpi_encode_csum( IOBUF out, MPI a, u16 *csum )
+mpi_write( IOBUF out, MPI a )
 {
     int i;
-    byte c;
     unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB;
     mpi_limb_t limb;
 
-#if BYTES_PER_MPI_LIMB != 4
-  #error Make this function work with other LIMB sizes
-#endif
+    /* fixme: use a->nbits if valid */
     if( nbits > MAX_EXTERN_MPI_BITS )
        log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
-    iobuf_put(out, (c=nbits >>8) ); *csum += c;
-    iobuf_put(out, (c=nbits) );     *csum += c;
+    iobuf_put(out, (nbits >>8) );
+    iobuf_put(out, (nbits) );
     for(i=a->nlimbs-1; i >= 0; i-- ) {
        limb = a->d[i];
-       iobuf_put(out, (c=limb >> 24) ); *csum += c;
-       iobuf_put(out, (c=limb >> 16) ); *csum += c;
-       iobuf_put(out, (c=limb >>  8) ); *csum += c;
-       iobuf_put(out, (c=limb      ) ); *csum += c;
+      #if BYTES_PER_MPI_LIMB == 4
+       iobuf_put(out, (limb >> 24) );
+       iobuf_put(out, (limb >> 16) );
+       iobuf_put(out, (limb >>  8) );
+       iobuf_put(out, (limb      ) );
+      #elif BYTES_PER_MPI_LIMB == 8
+       iobuf_put(out, (limb >> 56) );
+       iobuf_put(out, (limb >> 48) );
+       iobuf_put(out, (limb >> 40) );
+       iobuf_put(out, (limb >> 32) );
+       iobuf_put(out, (limb >> 24) );
+       iobuf_put(out, (limb >> 16) );
+       iobuf_put(out, (limb >>  8) );
+       iobuf_put(out, (limb      ) );
+      #else
+       #error Make this function work with other LIMB sizes
+      #endif
     }
     return 0;
 }
 
-/****************
- * encode the MPI into a newly allocated buffer, the buffer is
- * so constructed, that it can be used for mpi_write. The caller
- * must free the returned buffer. The buffer is allocated in the same
- * type of memory space as A is.
- */
-byte *
-mpi_encode_buffer( MPI a )
-{
-    abort();
-    return NULL;
-}
-
-/****************
- * write an mpi to out. This is a special function to handle
- * encrypted values. It simply writes the buffer a to OUT.
- * A is a special buffer, starting with 2 bytes giving it's length
- * (in big endian order) and 2 bytes giving it's length in bits (also
- * big endian)
- */
-int
-mpi_write( IOBUF out, byte *a)
-{
-    u16 dummy;
-    return mpi_write_csum( out, a, &dummy );
-}
-
-int
-mpi_write_csum( IOBUF out, byte *a, u16 *csum)
-{
-    int rc;
-    unsigned n;
-
-    n = *a++ << 8;
-    n |= *a++;
-    rc = iobuf_write(out, a, n );
-    for( ; n; n--, a++ )
-       *csum += *a;
-    return rc;
-}
 
 /****************
- * Decode an external representation and return an MPI
+ * Read an external representation of an mpi and return the MPI
  * The external format is a 16 bit unsigned value stored in network byte order,
  * giving the number of bits for the following integer. The integer is stored
  * with MSB first (left padded with zeroes to align on a byte boundary).
  */
 MPI
 #ifdef M_DEBUG
-mpi_debug_decode(IOBUF inp, unsigned *ret_nread, const char *info)
+mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info)
 #else
-mpi_decode(IOBUF inp, unsigned *ret_nread)
+mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
 #endif
 {
     int c, i, j;
@@ -144,12 +107,15 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
     nbytes = (nbits+7) / 8;
     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
   #ifdef M_DEBUG
-    val = mpi_debug_alloc( nlimbs, info );
+    val = secure? mpi_debug_alloc_secure( nlimbs, info )
+               : mpi_debug_alloc( nlimbs, info );
   #else
-    val = mpi_alloc( nlimbs );
+    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-- ) {
@@ -171,103 +137,6 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
 }
 
 
-/****************
- * Decode an MPI from the buffer, the buffer starts with two bytes giving
- * the length of the data to follow, the original data follows.
- * The MPI is alloced from secure MPI space
- */
-MPI
-#ifdef M_DEBUG
-mpi_debug_decode_buffer(byte *buffer, const char *info )
-#else
-mpi_decode_buffer(byte *buffer )
-#endif
-{
-    int i, j;
-    u16 buflen;
-    unsigned nbits, nbytes, nlimbs;
-    mpi_limb_t a;
-    byte *p = buffer;
-    MPI val;
-
-    if( !buffer )
-       log_bug("mpi_decode_buffer: no buffer\n");
-    buflen = *p++ << 8;
-    buflen |= *p++;
-    nbits = *p++ << 8;
-    nbits |= *p++;
-    nbytes = (nbits+7) / 8;
-    if( nbytes+2 != buflen )
-       log_bug("mpi_decode_buffer: length conflict\n");
-    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
-  #ifdef M_DEBUG
-    val = mpi_debug_alloc_secure( nlimbs, info );
-  #else
-    val = mpi_alloc_secure( nlimbs );
-  #endif
-    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++ ) {
-           a <<= 8;
-           a |= *p++;
-       }
-       i = 0;
-       val->d[j-1] = a;
-    }
-    return val;
-}
-
-
-/****************
- * Read a MPI from the external medium and return it in a newly allocated
- * buffer (This buffer is allocated in the secure memory space, because
- * we properly need this to decipher this string).
- * Return: the allocated string and in RET_NREAD the number of bytes
- *        read (including the 2 length bytes), the returned buffer will
- *        be prefixed with two bytes describing the length of the following
- *        data.
- */
-byte *
-mpi_read(IOBUF inp, unsigned *ret_nread)
-{
-    int c;
-    u16 buflen;
-    unsigned nbits, nbytes, nread;
-    byte *p, *buf;
-
-    if( (c = iobuf_get(inp)) == -1 )
-       return NULL;
-    nbits = c << 8;
-    if( (c = iobuf_get(inp)) == -1 )
-       return NULL;
-    nbits |= c;
-    if( nbits > MAX_EXTERN_MPI_BITS ) {
-       log_error("mpi too large (%u bits)\n", nbits);
-       return NULL;
-    }
-    nread = 2;
-
-    nbytes = (nbits+7) / 8;
-    buflen = nbytes + 2;
-    p = buf = m_alloc_secure( buflen+2 );
-    *p++ = buflen >> 8;
-    *p++ = buflen & 0xff;
-    *p++ = nbits >> 8;
-    *p++ = nbits & 0xff;
-    for( ; nbytes ; nbytes--, nread++ )
-       *p++ = iobuf_get(inp) & 0xff;
-
-    if( nread > *ret_nread )
-       log_error("Ooops: mpi crosses packet border");
-    else
-       *ret_nread = nread;
-    return buf;
-}
-
 
 /****************
  * Make a mpi from a character string.
@@ -390,3 +259,96 @@ mpi_get_keyid( MPI a, u32 *keyid )
 }
 
 
+/****************
+ * Return a m_alloced buffer with the MPI (msb first).
+ * NBYTES receives the length of this buffer. Caller must free the
+ * return string (This function does return a 0 byte buffer with NBYTES
+ * set to zero if the value of A is zero. If sign is not NULL, it will
+ * be set to the sign of the A.
+ */
+byte *
+mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
+{
+    byte *p, *buffer;
+    mpi_limb_t alimb;
+    int i;
+
+    if( sign )
+       *sign = a->sign;
+    *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
+    p = buffer = a->secure ? m_alloc_secure( *nbytes) : m_alloc( *nbytes );
+
+    for(i=a->nlimbs-1; i >= 0; i-- ) {
+       alimb = a->d[i];
+      #if BYTES_PER_MPI_LIMB == 4
+       *p++ = alimb >> 24;
+       *p++ = alimb >> 16;
+       *p++ = alimb >>  8;
+       *p++ = alimb      ;
+      #elif BYTES_PER_MPI_LIMB == 8
+       *p++ = alimb >> 56;
+       *p++ = alimb >> 48;
+       *p++ = alimb >> 40;
+       *p++ = alimb >> 32;
+       *p++ = alimb >> 24;
+       *p++ = alimb >> 16;
+       *p++ = alimb >>  8;
+       *p++ = alimb      ;
+      #else
+       #error please implement for this limb size.
+      #endif
+    }
+    return buffer;
+}
+
+/****************
+ * Use BUFFER to update MPI.
+ */
+void
+mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
+{
+    const byte *p;
+    mpi_limb_t alimb;
+    int nlimbs;
+    int i;
+
+    nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
+    RESIZE_IF_NEEDED(a, nlimbs);
+    a->sign = sign;
+
+    for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
+      #if BYTES_PER_MPI_LIMB == 4
+       alimb  = *p--       ;
+       alimb |= *p-- <<  8 ;
+       alimb |= *p-- << 16 ;
+       alimb |= *p-- << 24 ;
+      #elif BYTES_PER_MPI_LIMB == 8
+      #else
+       #error please implement for this limb size.
+      #endif
+       a->d[i++] = alimb;
+    }
+    if( p >= buffer ) {
+      #if BYTES_PER_MPI_LIMB == 4
+       alimb  = *p--       ;
+       if( p >= buffer ) alimb |= *p-- <<  8 ;
+       if( p >= buffer ) alimb |= *p-- << 16 ;
+       if( p >= buffer ) alimb |= *p-- << 24 ;
+      #elif BYTES_PER_MPI_LIMB == 8
+       alimb  = *p--       ;
+       if( p >= buffer ) alimb |= *p-- <<  8 ;
+       if( p >= buffer ) alimb |= *p-- << 16 ;
+       if( p >= buffer ) alimb |= *p-- << 24 ;
+       if( p >= buffer ) alimb |= *p-- << 32 ;
+       if( p >= buffer ) alimb |= *p-- << 40 ;
+       if( p >= buffer ) alimb |= *p-- << 48 ;
+       if( p >= buffer ) alimb |= *p-- << 56 ;
+      #else
+       #error please implement for this limb size.
+      #endif
+       a->d[i++] = alimb;
+    }
+    a->nlimbs = i;
+    assert( i == nlimbs );
+}
+
index 54095df..9ba9a8e 100644 (file)
@@ -456,3 +456,26 @@ m_is_secure( const void *p )
     return p && ((byte*)p)[-1] == MAGIC_SEC_BYTE;
 }
 
+
+/****************
+ * Make a copy of the memory block at a
+ */
+void *
+FNAME(copy)( void *a FNAMEPRT )
+{
+    void *b;
+    size_t n;
+
+    if( !a )
+       return a;
+
+    n = m_size(a);
+    if( m_is_secure(a) )
+       b = FNAME(alloc_secure)(n FNAMEARG);
+    else
+       b = FNAME(alloc)(n FNAMEARG);
+    memcpy(b, a, n );
+    return b;
+}
+
+