summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1997-12-09 13:46:23 +0100
committerWerner Koch <wk@gnupg.org>1997-12-09 13:46:23 +0100
commit935965049d424d3bb69efb672f9f44c36e7cbcb6 (patch)
tree37113923fa101828e1b43a8a71b9a85e17cd82a8
parentdetached signatures are working (diff)
downloadgnupg2-935965049d424d3bb69efb672f9f44c36e7cbcb6.tar.xz
gnupg2-935965049d424d3bb69efb672f9f44c36e7cbcb6.zip
fingerprints and self signatures added
-rw-r--r--TODO8
-rw-r--r--cipher/elgamal.c4
-rw-r--r--cipher/primegen.c15
-rw-r--r--cipher/rsa.c16
-rw-r--r--cipher/rsa.h1
-rw-r--r--g10/build-packet.c86
-rw-r--r--g10/free-packet.c21
-rw-r--r--g10/g10.c14
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/keygen.c200
-rw-r--r--g10/keyid.c107
-rw-r--r--g10/mainproc.c43
-rw-r--r--g10/options.h4
-rw-r--r--g10/packet.h8
-rw-r--r--g10/parse-packet.c108
-rw-r--r--g10/passphrase.c14
-rw-r--r--g10/seckey-cert.c237
-rw-r--r--g10/sig-check.c2
-rw-r--r--include/errors.h1
-rw-r--r--include/memory.h3
-rw-r--r--include/mpi.h24
-rw-r--r--mpi/mpicoder.c286
-rw-r--r--util/memory.c23
23 files changed, 783 insertions, 444 deletions
diff --git a/TODO b/TODO
index 03f4faa4b..21e51d0c1 100644
--- 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
@@ -24,10 +22,12 @@
* 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!
+
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index a7450e068..63ec06f57 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -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 );
diff --git a/cipher/primegen.c b/cipher/primegen.c
index d69f09ac3..49ec8f659 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -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 */
diff --git a/cipher/rsa.c b/cipher/rsa.c
index a1f08457b..db82b48d7 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -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;
+}
+
/****************
diff --git a/cipher/rsa.h b/cipher/rsa.h
index a9980d0bc..1b6d189bf 100644
--- a/cipher/rsa.h
+++ b/cipher/rsa.h
@@ -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 );
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 6d9957f17..25d708ceb 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -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;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index fa116ba62..dfd6f4b08 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -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);
}
diff --git a/g10/g10.c b/g10/g10.c
index 747cba196..88bde47cc 100644
--- 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;
diff --git a/g10/keydb.h b/g10/keydb.h
index 21423cfbb..bd8928086 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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 );
diff --git a/g10/keygen.c b/g10/keygen.c
index 3cbbf89e1..a4ed697c4 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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);
}
diff --git a/g10/keyid.c b/g10/keyid.c
index 7453754a2..e3a16d86b 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -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;
+}
+
+
+
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 9418da4e4..a04b0fc1f 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -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 )) ) {
diff --git a/g10/options.h b/g10/options.h
index 2b65db20c..a23412fc8 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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;
diff --git a/g10/packet.h b/g10/packet.h
index 5694c8a5b..57adebe5f 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -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*/
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 6aef1b4fe..5badb0ec4 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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
}
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 5a45f49bd..4e5e57bb3 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -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;
}
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 689f473c9..85d93b4f9 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -35,12 +35,20 @@
#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;
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 841423878..d5f0afb9e 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
return rc;
}
+
+
diff --git a/include/errors.h b/include/errors.h
index 7ad3181c4..cdd4a0549 100644
--- a/include/errors.h
+++ b/include/errors.h
@@ -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*/
diff --git a/include/memory.h b/include/memory.h
index aa8bb706d..32eb3906b 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -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
diff --git a/include/mpi.h b/include/mpi.h
index cf3623273..ce60f16a8 100644
--- a/include/mpi.h
+++ b/include/mpi.h
@@ -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 );
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index 23454c0f9..43b97beea 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -24,13 +24,13 @@
#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
@@ -39,89 +39,52 @@
* 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 );
+}
+
diff --git a/util/memory.c b/util/memory.c
index 54095df17..9ba9a8e82 100644
--- a/util/memory.c
+++ b/util/memory.c
@@ -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;
+}
+
+