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>
* Makefile.am (LDADD): Replaced W32LIBS by NETLIBS.

View File

@ -161,11 +161,17 @@ mpi_write (iobuf_t out, gcry_mpi_t a)
size_t nbytes;
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 );
if( !rc )
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;
}
@ -241,171 +247,195 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
static int
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
if( !pk->version )
iobuf_put( a, 3 );
else
iobuf_put( a, pk->version );
write_32(a, pk->timestamp );
if( pk->version < 4 ) {
u16 ndays;
if( pk->expiredate )
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays );
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
if ( !pk->version )
iobuf_put( a, 3 );
else
iobuf_put( a, pk->version );
write_32(a, pk->timestamp );
if ( pk->version < 4 )
{
u16 ndays;
if ( pk->expiredate )
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays );
}
iobuf_put(a, pk->pubkey_algo );
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
write_fake_data( a, pk->pkey[0] );
for(i=0; i < n; i++ )
mpi_write(a, pk->pkey[i] );
iobuf_put (a, pk->pubkey_algo );
n = pubkey_get_npkey ( pk->pubkey_algo );
if ( !n )
write_fake_data( a, pk->pkey[0] );
for (i=0; i < n && !rc ; i++ )
rc = mpi_write(a, pk->pkey[i] );
write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
rc = iobuf_write_temp( out, a );
if (!rc)
{
write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
rc = iobuf_write_temp ( out, a );
}
iobuf_close(a);
return rc;
iobuf_close(a);
return rc;
}
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
int rc = 0;
int i, nskey, npkey;
IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */
int rc = 0;
int i, nskey, npkey;
IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer. */
/* Write the version number - if none is specified, use 3 */
if( !sk->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sk->version );
write_32(a, sk->timestamp );
/* Write the version number - if none is specified, use 3 */
if ( !sk->version )
iobuf_put ( a, 3 );
else
iobuf_put ( a, sk->version );
write_32 (a, sk->timestamp );
/* v3 needs the expiration time */
if( sk->version < 4 ) {
u16 ndays;
if( sk->expiredate )
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays);
/* v3 needs the expiration time. */
if ( sk->version < 4 )
{
u16 ndays;
if ( sk->expiredate )
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays);
}
iobuf_put(a, sk->pubkey_algo );
/* get number of secret and public parameters. They are held in
one array first the public ones, then the secret ones */
nskey = pubkey_get_nskey( sk->pubkey_algo );
npkey = pubkey_get_npkey( sk->pubkey_algo );
/* If we don't have any public parameters - which is the case if
we don't know the algorithm used - the parameters are stored as
one blob in a faked (opaque) MPI */
if( !npkey ) {
write_fake_data( a, sk->skey[0] );
goto leave;
iobuf_put (a, sk->pubkey_algo );
/* Get number of secret and public parameters. They are held in one
array first the public ones, then the secret ones. */
nskey = pubkey_get_nskey ( sk->pubkey_algo );
npkey = pubkey_get_npkey ( sk->pubkey_algo );
/* If we don't have any public parameters - which is the case if we
don't know the algorithm used - the parameters are stored as one
blob in a faked (opaque) MPI. */
if ( !npkey )
{
write_fake_data( a, sk->skey[0] );
goto leave;
}
assert( npkey < nskey );
assert ( npkey < nskey );
/* Writing the public parameters is easy */
for(i=0; i < npkey; i++ )
mpi_write(a, sk->skey[i] );
/* build the header for protected (encrypted) secret parameters */
if( sk->is_protected ) {
if( is_RSA(sk->pubkey_algo) && sk->version < 4
&& !sk->protect.s2k.mode ) {
/* the simple rfc1991 (v3) way */
iobuf_put(a, sk->protect.algo );
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
/* Writing the public parameters is easy. */
for (i=0; i < npkey; i++ )
if ((rc = mpi_write (a, sk->skey[i])))
goto leave;
/* Build the header for protected (encrypted) secret parameters. */
if ( sk->is_protected )
{
if ( is_RSA(sk->pubkey_algo)
&& sk->version < 4
&& !sk->protect.s2k.mode )
{
/* The simple rfc1991 (v3) way. */
iobuf_put (a, sk->protect.algo );
iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
}
else {
/* OpenPGP protection according to rfc2440 */
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
iobuf_put(a, sk->protect.algo );
if( sk->protect.s2k.mode >= 1000 ) {
/* These modes are not possible in OpenPGP, we use them
to implement our extensions, 101 can be seen as a
private/experimental extension (this is not
specified in rfc2440 but the same scheme is used
for all other algorithm identifiers) */
iobuf_put(a, 101 );
iobuf_put(a, sk->protect.s2k.hash_algo );
iobuf_write(a, "GNU", 3 );
iobuf_put(a, sk->protect.s2k.mode - 1000 );
else
{
/* OpenPGP protection according to rfc2440. */
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
iobuf_put(a, sk->protect.algo );
if ( sk->protect.s2k.mode >= 1000 )
{
/* These modes are not possible in OpenPGP, we use them
to implement our extensions, 101 can be seen as a
private/experimental extension (this is not specified
in rfc2440 but the same scheme is used for all other
algorithm identifiers) */
iobuf_put(a, 101 );
iobuf_put(a, sk->protect.s2k.hash_algo );
iobuf_write(a, "GNU", 3 );
iobuf_put(a, sk->protect.s2k.mode - 1000 );
}
else {
iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo );
else
{
iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo );
}
if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 )
iobuf_write(a, sk->protect.s2k.salt, 8 );
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
if ( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 )
iobuf_write (a, sk->protect.s2k.salt, 8 );
/* For out special modes 1001, 1002 we do not need an IV */
if( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 )
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
if ( sk->protect.s2k.mode == 3 )
iobuf_put (a, sk->protect.s2k.count );
/* For our special modes 1001, 1002 we do not need an IV. */
if ( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 )
iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
}
}
else
iobuf_put(a, 0 );
else
iobuf_put (a, 0 );
if( sk->protect.s2k.mode == 1001 )
; /* GnuPG extension - don't write a secret key at all */
else if( sk->protect.s2k.mode == 1002 )
{ /* GnuPG extension - divert to OpenPGP smartcard. */
iobuf_put(a, sk->protect.ivlen ); /* length of the serial
number or 0 for no serial
number. */
/* The serial number gets stored in the IV field. */
iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
}
else if( sk->is_protected && sk->version >= 4 ) {
/* The secret key is protected - write it out as it is */
byte *p;
unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
iobuf_write (a, p, (ndatabits+7)/8 );
if ( sk->protect.s2k.mode == 1001 )
; /* GnuPG extension - don't write a secret key at all. */
else if ( sk->protect.s2k.mode == 1002 )
{
/* GnuPG extension - divert to OpenPGP smartcard. */
iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number
or 0 for no serial
number. */
/* The serial number gets stored in the IV field. */
iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
}
else if( sk->is_protected ) {
/* The secret key is protected te old v4 way. */
for( ; i < nskey; i++ ) {
byte *p;
unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8);
else if ( sk->is_protected && sk->version >= 4 )
{
/* The secret key is protected - write it out as it is. */
byte *p;
unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
iobuf_write (a, p, (ndatabits+7)/8 );
}
else if ( sk->is_protected )
{
/* The secret key is protected the old v4 way. */
for ( ; i < nskey; i++ )
{
byte *p;
unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8);
}
write_16(a, sk->csum );
write_16(a, sk->csum );
}
else {
/* non-protected key */
for( ; i < nskey; i++ )
mpi_write(a, sk->skey[i] );
write_16(a, sk->csum );
else
{
/* Non-protected key. */
for ( ; i < nskey; i++ )
if ( (rc = mpi_write (a, sk->skey[i])))
goto leave;
write_16 (a, sk->csum );
}
leave:
/* 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);
/* And finally write it out the real stream */
rc = iobuf_write_temp( out, a );
leave:
if (!rc)
{
/* 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);
/* And finally write it out the real stream */
rc = iobuf_write_temp( out, a );
}
iobuf_close(a); /* close the remporary buffer */
return rc;
iobuf_close(a); /* Close the remporary buffer */
return rc;
}
static int
@ -442,31 +472,35 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
static int
do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
write_version( a, ctb );
if( enc->throw_keyid ) {
write_32(a, 0 ); /* don't tell Eve who can decrypt the message */
write_32(a, 0 );
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
write_version( a, ctb );
if ( enc->throw_keyid )
{
write_32(a, 0 ); /* Don't tell Eve who can decrypt the message. */
write_32(a, 0 );
}
else {
write_32(a, enc->keyid[0] );
write_32(a, enc->keyid[1] );
else
{
write_32(a, enc->keyid[0] );
write_32(a, enc->keyid[1] );
}
iobuf_put(a,enc->pubkey_algo );
n = pubkey_get_nenc( enc->pubkey_algo );
if( !n )
write_fake_data( a, enc->data[0] );
for(i=0; i < n; i++ )
mpi_write(a, enc->data[i] );
iobuf_put(a,enc->pubkey_algo );
n = pubkey_get_nenc( enc->pubkey_algo );
if ( !n )
write_fake_data( a, enc->data[0] );
for (i=0; i < n && !rc ; i++ )
rc = mpi_write(a, enc->data[i] );
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
if (!rc)
{
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a );
}
iobuf_close(a);
return rc;
}
@ -1076,54 +1110,59 @@ free_notation(struct notation *notation)
static int
do_signature( IOBUF out, int ctb, PKT_signature *sig )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
if( !sig->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sig->version );
if( sig->version < 4 )
iobuf_put(a, 5 ); /* constant */
iobuf_put(a, sig->sig_class );
if( sig->version < 4 ) {
write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] );
if ( !sig->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sig->version );
if ( sig->version < 4 )
iobuf_put (a, 5 ); /* Constant */
iobuf_put (a, sig->sig_class );
if ( sig->version < 4 )
{
write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] );
}
iobuf_put(a, sig->pubkey_algo );
iobuf_put(a, sig->digest_algo );
if( sig->version >= 4 ) {
size_t nn;
/* timestamp and keyid must have been packed into the
* subpackets prior to the call of this function, because
* these subpackets are hashed */
nn = sig->hashed? sig->hashed->len : 0;
write_16(a, nn);
if( nn )
iobuf_write( a, sig->hashed->data, nn );
nn = sig->unhashed? sig->unhashed->len : 0;
write_16(a, nn);
if( nn )
iobuf_write( a, sig->unhashed->data, nn );
iobuf_put(a, sig->pubkey_algo );
iobuf_put(a, sig->digest_algo );
if ( sig->version >= 4 )
{
size_t nn;
/* Timestamp and keyid must have been packed into the subpackets
prior to the call of this function, because these subpackets
are hashed. */
nn = sig->hashed? sig->hashed->len : 0;
write_16(a, nn);
if (nn)
iobuf_write( a, sig->hashed->data, nn );
nn = sig->unhashed? sig->unhashed->len : 0;
write_16(a, nn);
if (nn)
iobuf_write( a, sig->unhashed->data, nn );
}
iobuf_put(a, sig->digest_start[0] );
iobuf_put(a, sig->digest_start[1] );
n = pubkey_get_nsig( sig->pubkey_algo );
if( !n )
write_fake_data( a, sig->data[0] );
for(i=0; i < n; i++ )
mpi_write(a, sig->data[i] );
iobuf_put(a, sig->digest_start[0] );
iobuf_put(a, sig->digest_start[1] );
n = pubkey_get_nsig( sig->pubkey_algo );
if ( !n )
write_fake_data( a, sig->data[0] );
for (i=0; i < n && !rc ; i++ )
rc = mpi_write(a, sig->data[i] );
if( is_RSA(sig->pubkey_algo) && sig->version < 4 )
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
else
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a );
if (!rc)
{
if ( is_RSA(sig->pubkey_algo) && sig->version < 4 )
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
else
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp( out, a );
}
iobuf_close(a);
return rc;
iobuf_close(a);
return rc;
}

View File

@ -299,9 +299,9 @@ import_print_stats (void *hd)
log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id );
if( stats->imported || stats->imported_rsa ) {
log_info(_(" imported: %lu"), stats->imported );
if( stats->imported_rsa )
fprintf(stderr, " (RSA: %lu)", stats->imported_rsa );
putc('\n', stderr);
if (stats->imported_rsa)
log_printf (" (RSA: %lu)", stats->imported_rsa );
log_printf ("\n");
}
if( 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 )
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
log_printf ("\n");
}
if( !uidnode )
@ -1108,7 +1108,7 @@ import_secret_one( const char *fname, KBNODE keyblock,
if( uidnode )
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
log_printf ("\n");
}
stats->secret_read++;