1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-02-07 17:33:02 +01:00

Fixed a bug with very long keys.

This commit is contained in:
Werner Koch 2006-10-18 14:28:52 +00:00
parent be410be660
commit 2a514d34df
3 changed files with 257 additions and 210 deletions

View File

@ -1,3 +1,11 @@
2006-10-18 Werner Koch <wk@g10code.com>
* import.c (import_print_stats): Use log_printf.
* build-packet.c (do_public_key): Care about mpi_write errors.
(do_secret_key, do_pubkey_enc, do_signature): Ditto.
(mpi_write): Print an extra warning on error.
2006-10-17 Werner Koch <wk@g10code.com> 2006-10-17 Werner Koch <wk@g10code.com>
* Makefile.am (LDADD): Replaced W32LIBS by NETLIBS. * Makefile.am (LDADD): Replaced W32LIBS by NETLIBS.

View File

@ -161,10 +161,16 @@ mpi_write (iobuf_t out, gcry_mpi_t a)
size_t nbytes; size_t nbytes;
int rc; int rc;
nbytes = (MAX_EXTERN_MPI_BITS+7)/8; nbytes = (MAX_EXTERN_MPI_BITS+7)/8 + 2; /* 2 is for the mpi length. */
rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a );
if( !rc ) if( !rc )
rc = iobuf_write( out, buffer, nbytes ); rc = iobuf_write( out, buffer, nbytes );
else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT )
{
log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a));
/* The buffer was too small. We better tell the user about the MPI. */
rc = gpg_error (GPG_ERR_TOO_LARGE);
}
return rc; return rc;
} }
@ -250,7 +256,8 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
else else
iobuf_put( a, pk->version ); iobuf_put( a, pk->version );
write_32(a, pk->timestamp ); write_32(a, pk->timestamp );
if( pk->version < 4 ) { if ( pk->version < 4 )
{
u16 ndays; u16 ndays;
if ( pk->expiredate ) if ( pk->expiredate )
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
@ -262,11 +269,14 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
n = pubkey_get_npkey ( pk->pubkey_algo ); n = pubkey_get_npkey ( pk->pubkey_algo );
if ( !n ) if ( !n )
write_fake_data( a, pk->pkey[0] ); write_fake_data( a, pk->pkey[0] );
for(i=0; i < n; i++ ) for (i=0; i < n && !rc ; i++ )
mpi_write(a, pk->pkey[i] ); rc = mpi_write(a, pk->pkey[i] );
if (!rc)
{
write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes); write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
rc = iobuf_write_temp ( out, a ); rc = iobuf_write_temp ( out, a );
}
iobuf_close(a); iobuf_close(a);
return rc; return rc;
@ -278,7 +288,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{ {
int rc = 0; int rc = 0;
int i, nskey, npkey; int i, nskey, npkey;
IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer. */
/* Write the version number - if none is specified, use 3 */ /* Write the version number - if none is specified, use 3 */
if ( !sk->version ) if ( !sk->version )
@ -287,8 +297,9 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
iobuf_put ( a, sk->version ); iobuf_put ( a, sk->version );
write_32 (a, sk->timestamp ); write_32 (a, sk->timestamp );
/* v3 needs the expiration time */ /* v3 needs the expiration time. */
if( sk->version < 4 ) { if ( sk->version < 4 )
{
u16 ndays; u16 ndays;
if ( sk->expiredate ) if ( sk->expiredate )
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
@ -299,58 +310,67 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
iobuf_put (a, sk->pubkey_algo ); iobuf_put (a, sk->pubkey_algo );
/* get number of secret and public parameters. They are held in /* Get number of secret and public parameters. They are held in one
one array first the public ones, then the secret ones */ array first the public ones, then the secret ones. */
nskey = pubkey_get_nskey ( sk->pubkey_algo ); nskey = pubkey_get_nskey ( sk->pubkey_algo );
npkey = pubkey_get_npkey ( sk->pubkey_algo ); npkey = pubkey_get_npkey ( sk->pubkey_algo );
/* If we don't have any public parameters - which is the case if /* If we don't have any public parameters - which is the case if we
we don't know the algorithm used - the parameters are stored as don't know the algorithm used - the parameters are stored as one
one blob in a faked (opaque) MPI */ blob in a faked (opaque) MPI. */
if( !npkey ) { if ( !npkey )
{
write_fake_data( a, sk->skey[0] ); write_fake_data( a, sk->skey[0] );
goto leave; goto leave;
} }
assert ( npkey < nskey ); assert ( npkey < nskey );
/* Writing the public parameters is easy */ /* Writing the public parameters is easy. */
for (i=0; i < npkey; i++ ) for (i=0; i < npkey; i++ )
mpi_write(a, sk->skey[i] ); if ((rc = mpi_write (a, sk->skey[i])))
goto leave;
/* build the header for protected (encrypted) secret parameters */ /* Build the header for protected (encrypted) secret parameters. */
if( sk->is_protected ) { if ( sk->is_protected )
if( is_RSA(sk->pubkey_algo) && sk->version < 4 {
&& !sk->protect.s2k.mode ) { if ( is_RSA(sk->pubkey_algo)
/* the simple rfc1991 (v3) way */ && sk->version < 4
&& !sk->protect.s2k.mode )
{
/* The simple rfc1991 (v3) way. */
iobuf_put (a, sk->protect.algo ); iobuf_put (a, sk->protect.algo );
iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
} }
else { else
/* OpenPGP protection according to rfc2440 */ {
/* OpenPGP protection according to rfc2440. */
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff ); iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
iobuf_put(a, sk->protect.algo ); iobuf_put(a, sk->protect.algo );
if( sk->protect.s2k.mode >= 1000 ) { if ( sk->protect.s2k.mode >= 1000 )
{
/* These modes are not possible in OpenPGP, we use them /* These modes are not possible in OpenPGP, we use them
to implement our extensions, 101 can be seen as a to implement our extensions, 101 can be seen as a
private/experimental extension (this is not private/experimental extension (this is not specified
specified in rfc2440 but the same scheme is used in rfc2440 but the same scheme is used for all other
for all other algorithm identifiers) */ algorithm identifiers) */
iobuf_put(a, 101 ); iobuf_put(a, 101 );
iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_put(a, sk->protect.s2k.hash_algo );
iobuf_write(a, "GNU", 3 ); iobuf_write(a, "GNU", 3 );
iobuf_put(a, sk->protect.s2k.mode - 1000 ); iobuf_put(a, sk->protect.s2k.mode - 1000 );
} }
else { else
{
iobuf_put(a, sk->protect.s2k.mode ); iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_put(a, sk->protect.s2k.hash_algo );
} }
if ( sk->protect.s2k.mode == 1 if ( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 ) || sk->protect.s2k.mode == 3 )
iobuf_write (a, sk->protect.s2k.salt, 8 ); iobuf_write (a, sk->protect.s2k.salt, 8 );
if ( sk->protect.s2k.mode == 3 ) if ( sk->protect.s2k.mode == 3 )
iobuf_put (a, sk->protect.s2k.count ); iobuf_put (a, sk->protect.s2k.count );
/* For out special modes 1001, 1002 we do not need an IV */ /* For our special modes 1001, 1002 we do not need an IV. */
if ( sk->protect.s2k.mode != 1001 if ( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 ) && sk->protect.s2k.mode != 1002 )
iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
@ -360,17 +380,19 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
iobuf_put (a, 0 ); iobuf_put (a, 0 );
if ( sk->protect.s2k.mode == 1001 ) if ( sk->protect.s2k.mode == 1001 )
; /* GnuPG extension - don't write a secret key at all */ ; /* GnuPG extension - don't write a secret key at all. */
else if ( sk->protect.s2k.mode == 1002 ) else if ( sk->protect.s2k.mode == 1002 )
{ /* GnuPG extension - divert to OpenPGP smartcard. */ {
iobuf_put(a, sk->protect.ivlen ); /* length of the serial /* GnuPG extension - divert to OpenPGP smartcard. */
number or 0 for no serial iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number
or 0 for no serial
number. */ number. */
/* The serial number gets stored in the IV field. */ /* The serial number gets stored in the IV field. */
iobuf_write(a, sk->protect.iv, sk->protect.ivlen); iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
} }
else if( sk->is_protected && sk->version >= 4 ) { else if ( sk->is_protected && sk->version >= 4 )
/* The secret key is protected - write it out as it is */ {
/* The secret key is protected - write it out as it is. */
byte *p; byte *p;
unsigned int ndatabits; unsigned int ndatabits;
@ -378,9 +400,11 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits ); p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
iobuf_write (a, p, (ndatabits+7)/8 ); iobuf_write (a, p, (ndatabits+7)/8 );
} }
else if( sk->is_protected ) { else if ( sk->is_protected )
/* The secret key is protected te old v4 way. */ {
for( ; i < nskey; i++ ) { /* The secret key is protected the old v4 way. */
for ( ; i < nskey; i++ )
{
byte *p; byte *p;
unsigned int ndatabits; unsigned int ndatabits;
@ -390,21 +414,27 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
} }
write_16(a, sk->csum ); write_16(a, sk->csum );
} }
else { else
/* non-protected key */ {
/* Non-protected key. */
for ( ; i < nskey; i++ ) for ( ; i < nskey; i++ )
mpi_write(a, sk->skey[i] ); if ( (rc = mpi_write (a, sk->skey[i])))
goto leave;
write_16 (a, sk->csum ); write_16 (a, sk->csum );
} }
leave: leave:
/* Build the header of the packet - which we must do after writing all if (!rc)
the other stuff, so that we know the length of the packet */ {
/* Build the header of the packet - which we must do after
writing all the other stuff, so that we know the length of
the packet */
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes); write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes);
/* And finally write it out the real stream */ /* And finally write it out the real stream */
rc = iobuf_write_temp( out, a ); rc = iobuf_write_temp( out, a );
}
iobuf_close(a); /* close the remporary buffer */ iobuf_close(a); /* Close the remporary buffer */
return rc; return rc;
} }
@ -447,11 +477,13 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
IOBUF a = iobuf_temp(); IOBUF a = iobuf_temp();
write_version( a, ctb ); write_version( a, ctb );
if( enc->throw_keyid ) { if ( enc->throw_keyid )
write_32(a, 0 ); /* don't tell Eve who can decrypt the message */ {
write_32(a, 0 ); /* Don't tell Eve who can decrypt the message. */
write_32(a, 0 ); write_32(a, 0 );
} }
else { else
{
write_32(a, enc->keyid[0] ); write_32(a, enc->keyid[0] );
write_32(a, enc->keyid[1] ); write_32(a, enc->keyid[1] );
} }
@ -459,12 +491,14 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
n = pubkey_get_nenc( enc->pubkey_algo ); n = pubkey_get_nenc( enc->pubkey_algo );
if ( !n ) if ( !n )
write_fake_data( a, enc->data[0] ); write_fake_data( a, enc->data[0] );
for(i=0; i < n; i++ ) for (i=0; i < n && !rc ; i++ )
mpi_write(a, enc->data[i] ); rc = mpi_write(a, enc->data[i] );
if (!rc)
{
write_header(out, ctb, iobuf_get_temp_length(a) ); write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a ); rc = iobuf_write_temp( out, a );
}
iobuf_close(a); iobuf_close(a);
return rc; return rc;
} }
@ -1085,20 +1119,22 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
else else
iobuf_put( a, sig->version ); iobuf_put( a, sig->version );
if ( sig->version < 4 ) if ( sig->version < 4 )
iobuf_put(a, 5 ); /* constant */ iobuf_put (a, 5 ); /* Constant */
iobuf_put (a, sig->sig_class ); iobuf_put (a, sig->sig_class );
if( sig->version < 4 ) { if ( sig->version < 4 )
{
write_32(a, sig->timestamp ); write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] ); write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] ); write_32(a, sig->keyid[1] );
} }
iobuf_put(a, sig->pubkey_algo ); iobuf_put(a, sig->pubkey_algo );
iobuf_put(a, sig->digest_algo ); iobuf_put(a, sig->digest_algo );
if( sig->version >= 4 ) { if ( sig->version >= 4 )
{
size_t nn; size_t nn;
/* timestamp and keyid must have been packed into the /* Timestamp and keyid must have been packed into the subpackets
* subpackets prior to the call of this function, because prior to the call of this function, because these subpackets
* these subpackets are hashed */ are hashed. */
nn = sig->hashed? sig->hashed->len : 0; nn = sig->hashed? sig->hashed->len : 0;
write_16(a, nn); write_16(a, nn);
if (nn) if (nn)
@ -1113,14 +1149,17 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
n = pubkey_get_nsig( sig->pubkey_algo ); n = pubkey_get_nsig( sig->pubkey_algo );
if ( !n ) if ( !n )
write_fake_data( a, sig->data[0] ); write_fake_data( a, sig->data[0] );
for(i=0; i < n; i++ ) for (i=0; i < n && !rc ; i++ )
mpi_write(a, sig->data[i] ); rc = mpi_write(a, sig->data[i] );
if (!rc)
{
if ( is_RSA(sig->pubkey_algo) && sig->version < 4 ) if ( is_RSA(sig->pubkey_algo) && sig->version < 4 )
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
else else
write_header(out, ctb, iobuf_get_temp_length(a) ); write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a ); rc = iobuf_write_temp( out, a );
}
iobuf_close(a); iobuf_close(a);
return rc; return rc;

View File

@ -300,8 +300,8 @@ import_print_stats (void *hd)
if( stats->imported || stats->imported_rsa ) { if( stats->imported || stats->imported_rsa ) {
log_info(_(" imported: %lu"), stats->imported ); log_info(_(" imported: %lu"), stats->imported );
if (stats->imported_rsa) if (stats->imported_rsa)
fprintf(stderr, " (RSA: %lu)", stats->imported_rsa ); log_printf (" (RSA: %lu)", stats->imported_rsa );
putc('\n', stderr); log_printf ("\n");
} }
if( stats->unchanged ) if( stats->unchanged )
log_info(_(" unchanged: %lu\n"), stats->unchanged ); log_info(_(" unchanged: %lu\n"), stats->unchanged );
@ -711,7 +711,7 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
if( uidnode ) if( uidnode )
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len ); uidnode->pkt->pkt.user_id->len );
putc('\n', stderr); log_printf ("\n");
} }
if( !uidnode ) if( !uidnode )
@ -1108,7 +1108,7 @@ import_secret_one( const char *fname, KBNODE keyblock,
if( uidnode ) if( uidnode )
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len ); uidnode->pkt->pkt.user_id->len );
putc('\n', stderr); log_printf ("\n");
} }
stats->secret_read++; stats->secret_read++;