1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

extensions are now working and fixed a lot of bugs

This commit is contained in:
Werner Koch 1998-06-15 15:41:04 +00:00
parent e662bf708b
commit 6e1ca6b80f
40 changed files with 350 additions and 454 deletions

View file

@ -1,6 +1,13 @@
Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (checksum_u16): Fixed a stupid bug which caused a
wrong checksum calculation for the secret key protection and
add a backward compatibility option.
* g10.c (main): Add option --emulate-checksum-bug.
Thu Jun 11 13:26:44 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h: Mjor chnages to the structure of public key material
* packet.h: Major changes to the structure of public key material
which is now stored in an array and not anaymore in a union of
algorithm specific structures. These is needed to make the system
more extendable and makes a lot of stuff much simpler. Changed

View file

@ -164,6 +164,7 @@ static ARGPARSE_OPTS opts[] = {
{ 553, "skip-verify",0, "@" },
{ 557, "compress-keys",0, "@"},
{ 559, "always-trust", 0, "@"},
{ 562, "emulate-checksum-bug", 0, "@"},
{0} };
@ -310,11 +311,6 @@ wrong_args( const char *text)
static void
set_debug(void)
{
volatile char *p = g10_malloc(1);
volatile MPI a = g10m_new(1);
*p = g10c_get_random_byte( 0 );
if( opt.debug & DBG_MEMORY_VALUE )
memory_debug_mode = 1;
if( opt.debug & DBG_MEMSTAT_VALUE )
@ -598,6 +594,7 @@ main( int argc, char **argv )
case 559: opt.always_trust = 1; break;
case 560: register_cipher_extension(pargs.r.ret_str); break;
case 561: opt.rfc1991 = 1; break;
case 562: opt.emulate_bugs |= 1; break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@ -1111,9 +1108,8 @@ print_mds( const char *fname, int algo )
md_enable( md, DIGEST_ALGO_MD5 );
md_enable( md, DIGEST_ALGO_SHA1 );
md_enable( md, DIGEST_ALGO_RMD160 );
#ifdef WITH_TIGER_HASH
md_enable( md, DIGEST_ALGO_TIGER );
#endif
if( !check_digest_algo(DIGEST_ALGO_TIGER) )
md_enable( md, DIGEST_ALGO_TIGER );
}
while( (n=fread( buf, 1, DIM(buf), fp )) )
@ -1134,10 +1130,10 @@ print_mds( const char *fname, int algo )
print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 );
printf("\n%sRMD160 = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
#ifdef WITH_TIGER_HASH
printf("\n%s TIGER = ", fname?pname:"" );
if( !check_digest_algo(DIGEST_ALGO_TIGER) ) {
printf("\n%s TIGER = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 );
#endif
}
}
putchar('\n');
}

View file

@ -129,7 +129,7 @@ set_debug(void)
if( opt.debug & DBG_MPI_VALUE )
mpi_debug_mode = 1;
if( opt.debug & DBG_CIPHER_VALUE )
cipher_debug_mode = 1;
g10c_debug_mode = 1;
if( opt.debug & DBG_IOBUF_VALUE )
iobuf_debug_mode = 1;
}

View file

@ -168,7 +168,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->is_protected = 0;
skc->protect.algo = 0;
skc->csum = checksum_mpi( skc->skey[3] );
skc->csum = checksum_mpi_counted_nbits( skc->skey[3] );
if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
*ret_skc = copy_secret_cert( NULL, skc );
@ -232,10 +232,10 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->d.rsa.rsa_p = sk.p;
skc->d.rsa.rsa_q = sk.q;
skc->d.rsa.rsa_u = sk.u;
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 );
skc->d.rsa.csum = checksum_mpi_counted_nbits( skc->d.rsa.rsa_d );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_p );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_q );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_u );
if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
*ret_skc = copy_secret_cert( NULL, skc );
@ -244,7 +244,8 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
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 );
skc->d.rsa.csum += checksum_counted_nbits(
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) );
@ -314,7 +315,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->is_protected = 0;
skc->protect.algo = 0;
skc->csum = checksum_mpi( skc->skey[4] );
skc->csum = checksum_mpi_counted_nbits( skc->skey[4] );
if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
*ret_skc = copy_secret_cert( NULL, skc );

View file

@ -49,6 +49,7 @@ void trap_unaligned(void);
u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a );
u16 checksum_mpi_counted_nbits( MPI a );
/*-- encode.c --*/
int encode_symmetric( const char *filename );
@ -85,7 +86,8 @@ IOBUF open_sigfile( const char *iname );
/*-- seskey.c --*/
void make_session_key( DEK *dek );
MPI encode_session_key( DEK *dek, unsigned nbits );
MPI encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits );
MPI encode_md_value( int pubkey_algo, MD_HANDLE md,
int hash_algo, unsigned nbits );
/*-- comment.c --*/
KBNODE make_comment_node( const char *s );

View file

@ -246,7 +246,8 @@ proc_plaintext( CTX c, PACKET *pkt )
/*md_start_debug(c->mfx.md, "proc_plaintext");*/
md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
md_enable( c->mfx.md, DIGEST_ALGO_TIGER );
if( !check_digest_algo(DIGEST_ALGO_TIGER) )
md_enable( c->mfx.md, DIGEST_ALGO_TIGER );
rc = handle_plaintext( pt, &c->mfx );
if( rc )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));

View file

@ -28,7 +28,15 @@
#endif
#include "util.h"
#include "main.h"
#include "options.h"
volatile int
pull_in_libs(void)
{
g10m_revision_string(0);
g10c_revision_string(0);
g10u_revision_string(0);
}
#if defined(__linux__) && defined(__alpha__)
@ -63,7 +71,22 @@ checksum_u16( unsigned n )
u16 a;
a = (n >> 8) & 0xff;
a |= n & 0xff;
if( opt.emulate_bugs & 1 ) {
a |= n & 0xff;
log_debug("csum_u16 emulated for n=%u\n", n);
}
else
a += n & 0xff;
return a;
}
static u16
checksum_u16_nobug( unsigned n )
{
u16 a;
a = (n >> 8) & 0xff;
a += n & 0xff;
return a;
}
@ -83,12 +106,43 @@ checksum_mpi( MPI a )
u16 csum;
byte *buffer;
unsigned nbytes;
unsigned nbits;
buffer = mpi_get_buffer( a, &nbytes, NULL );
csum = checksum_u16( mpi_get_nbits(a) );
/* some versions of gpg encode wrong values for the length of an mpi
* so that mpi_get_nbits() which counts the mpi yields another (shorter)
* value than the one store with the mpi. mpi_get_nbit_info() returns
* this stored value if it is still available.
*/
if( opt.emulate_bugs & 1 )
nbits = 0;
else
nbits = mpi_get_nbit_info(a);
if( !nbits )
nbits = mpi_get_nbits(a);
csum = checksum_u16( nbits );
csum += checksum( buffer, nbytes );
m_free( buffer );
return csum;
}
/****************
* This is the correct function
*/
u16
checksum_mpi_counted_nbits( MPI a )
{
u16 csum;
byte *buffer;
unsigned nbytes;
unsigned nbits;
buffer = mpi_get_buffer( a, &nbytes, NULL );
nbits = mpi_get_nbits(a);
csum = checksum_u16_nobug( nbits );
csum += checksum( buffer, nbytes );
m_free( buffer );
return csum;
}

View file

@ -48,6 +48,7 @@ struct {
int compress_keys;
int always_trust;
int rfc1991;
unsigned emulate_bugs; /* bug emulation flags */
} opt;

View file

@ -64,6 +64,7 @@ static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static unsigned short
read_16(IOBUF inp)
{
@ -1006,9 +1007,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
cert->csum = read_16(inp); pktlen -= 2;
if( list_mode ) {
printf("\telg x: ");
mpi_print(stdout, cert->skey[3], mpi_print_mode );
putchar('\n');
printf("\t[secret value x is not shown]\n"
"\tchecksum: %04hx\n", cert->csum);
}
@ -1174,8 +1172,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
printf(" %02x", temp[i] );
putchar('\n');
}
if( cert->protect.algo == CIPHER_ALGO_BLOWFISH160 )
memcpy(cert->protect.iv, temp, 8 );
memcpy(cert->protect.iv, temp, 8 );
/* old version, we don't have a S2K, so we fake one */
cert->protect.s2k.mode = 0;
cert->protect.s2k.hash_algo = DIGEST_ALGO_MD5;

View file

@ -39,7 +39,7 @@ do_check( PKT_secret_cert *cert )
{
byte *buffer;
u16 csum=0;
int res;
int i, res;
unsigned nbytes;
if( cert->is_protected ) { /* remove the protection */
@ -60,60 +60,34 @@ do_check( PKT_secret_cert *cert )
CIPHER_MODE_AUTO_CFB, 1);
cipher_setkey( cipher_hd, dek->key, dek->keylen );
cipher_setiv( cipher_hd, NULL );
m_free(dek); /* pw is in secure memory, so m_free() burns it */
m_free(dek);
save_cert = copy_secret_cert( NULL, cert );
memcpy(save_iv, cert->protect.iv, 8 );
cipher_decrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 );
switch( cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_ELGAMAL_E:
/* FIXME: removed ELG knowledge from this function */
buffer = mpi_get_secure_buffer( cert->skey[3], &nbytes, NULL );
csum = 0;
for(i=pubkey_get_npkey(cert->pubkey_algo);
i < pubkey_get_nskey(cert->pubkey_algo); i++ ) {
buffer = mpi_get_secure_buffer( cert->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( cert->skey[3], buffer, nbytes, 0 );
csum = checksum_mpi( cert->skey[3] );
mpi_set_buffer( cert->skey[i], buffer, nbytes, 0 );
csum += checksum_mpi( cert->skey[i] );
m_free( buffer );
break;
case PUBKEY_ALGO_DSA:
buffer = mpi_get_secure_buffer( cert->skey[4], &nbytes, NULL );
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( cert->skey[4], buffer, nbytes, 0 );
csum = checksum_mpi( cert->skey[4] );
m_free( buffer );
break;
case PUBKEY_ALGO_RSA:
case PUBKEY_ALGO_RSA_E:
case PUBKEY_ALGO_RSA_S:
csum = 0;
#define X(a) do { \
buffer = mpi_get_secure_buffer( cert->skey[(a)], \
&nbytes, NULL ); \
csum += checksum_u16( nbytes*8 ); \
cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); \
csum += checksum( buffer, nbytes ); \
mpi_set_buffer(cert->skey[(a)], buffer, nbytes, 0 ); \
m_free( buffer ); \
} while(0)
X(2);
X(3);
X(4);
X(5);
#undef X
break;
default: BUG();
}
if( opt.emulate_bugs & 1 ) {
log_debug("secret key csum is=%04hx should=%04hx algos=%d/%d\n",
csum, cert->csum, cert->pubkey_algo,cert->protect.algo );
csum = cert->csum;
}
cipher_close( cipher_hd );
/* now let's see whether we have used the right passphrase */
if( csum != cert->csum ) {
if( csum != cert->csum ) {
copy_secret_cert( cert, save_cert );
free_secret_cert( save_cert );
memcpy( cert->protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
copy_secret_cert( cert, save_cert );
free_secret_cert( save_cert );
memcpy( cert->protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
/* the checksum may fail, so we also check the key itself */
res = pubkey_check_secret_key( cert->pubkey_algo, cert->skey );
if( res ) {
copy_secret_cert( cert, save_cert );
@ -124,37 +98,11 @@ do_check( PKT_secret_cert *cert )
free_secret_cert( save_cert );
cert->is_protected = 0;
}
else { /* not protected */
switch( cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL_E:
case PUBKEY_ALGO_ELGAMAL:
csum = checksum_mpi( cert->skey[3] );
break;
case PUBKEY_ALGO_DSA:
csum = checksum_mpi( cert->skey[4] );
break;
case PUBKEY_ALGO_RSA_E:
case PUBKEY_ALGO_RSA_S:
case PUBKEY_ALGO_RSA:
csum =0;
buffer = mpi_get_buffer( cert->skey[2], &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
buffer = mpi_get_buffer( cert->skey[3], &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
buffer = mpi_get_buffer( cert->skey[4], &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
buffer = mpi_get_buffer( cert->skey[5], &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
break;
default: BUG();
else { /* not protected, assume it is okay if the checksum is okay */
csum = 0;
for(i=pubkey_get_npkey(cert->pubkey_algo);
i < pubkey_get_nskey(cert->pubkey_algo); i++ ) {
csum += checksum_mpi( cert->skey[i] );
}
if( csum != cert->csum )
return G10ERR_CHECKSUM;
@ -212,34 +160,6 @@ is_secret_key_protected( PKT_secret_cert *cert )
}
static int
do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned),
CIPHER_HANDLE fnc_hd, PKT_secret_cert *cert )
{
byte *buffer;
unsigned nbytes;
switch( cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL_E:
case PUBKEY_ALGO_ELGAMAL:
buffer = mpi_get_buffer( cert->skey[3], &nbytes, NULL );
(*fnc)( fnc_hd, buffer, buffer, nbytes );
mpi_set_buffer( cert->skey[3], buffer, nbytes, 0 );
m_free( buffer );
break;
case PUBKEY_ALGO_DSA:
buffer = mpi_get_buffer( cert->skey[4], &nbytes, NULL );
(*fnc)( fnc_hd, buffer, buffer, nbytes );
mpi_set_buffer( cert->skey[4], buffer, nbytes, 0 );
m_free( buffer );
break;
default: return G10ERR_PUBKEY_ALGO;
}
return 0;
}
/****************
* Protect the secret key certificate with the passphrase from DEK
@ -247,7 +167,10 @@ do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned),
int
protect_secret_key( PKT_secret_cert *cert, DEK *dek )
{
int rc=0;
int i, rc = 0;
byte *buffer;
unsigned nbytes;
u16 csum;
if( !dek )
return 0;
@ -263,8 +186,21 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek )
cipher_setkey( cipher_hd, dek->key, dek->keylen );
cipher_setiv( cipher_hd, NULL );
cipher_encrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 );
if( !do_protect( &cipher_encrypt, cipher_hd, cert ) )
cert->is_protected = 1;
/* NOTE: we always recalculate the checksum because there are some
* test releases which calculated it wrong */
csum = 0;
for(i=pubkey_get_npkey(cert->pubkey_algo);
i < pubkey_get_nskey(cert->pubkey_algo); i++ ) {
csum += checksum_mpi_counted_nbits( cert->skey[i] );
buffer = mpi_get_buffer( cert->skey[i], &nbytes, NULL );
log_debug("protecing i=%d csum=%04hx nbytes=%u\n", i, csum, nbytes );
cipher_sync( cipher_hd );
cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( cert->skey[i], buffer, nbytes, 0 );
m_free( buffer );
}
cert->csum = csum;
cert->is_protected = 1;
cipher_close( cipher_hd );
}
}

View file

@ -144,13 +144,25 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits,
MPI
encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits )
encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits )
{
int algo = hash_algo? hash_algo : md_get_algo(md);
const byte *asn;
size_t asnlen, mdlen;
MPI frame;
asn = md_asn_oid( algo, &asnlen, &mdlen );
return do_encode_md( md, algo, mdlen, nbits, asn, asnlen );
if( pubkey_algo == PUBKEY_ALGO_DSA ) {
frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo)
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
: mpi_alloc((md_digest_length(hash_algo)
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
mpi_set_buffer( frame, md_read(md, hash_algo),
md_digest_length(hash_algo), 0 );
}
else {
asn = md_asn_oid( algo, &asnlen, &mdlen );
frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen );
}
return frame;
}

View file

@ -32,6 +32,11 @@
#include "main.h"
#include "status.h"
struct cmp_help_context_s {
PKT_signature *sig;
MD_HANDLE md;
};
static int do_check( PKT_public_cert *pkc, PKT_signature *sig,
MD_HANDLE digest );
@ -62,11 +67,87 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
}
/****************
* This function gets called by pubkey_verify() if the algorithm needs it.
*/
static int
cmp_help( void *opaque, MPI result )
{
#if 0 /* we do not use this anymore */
int rc=0, i, j, c, old_enc;
byte *dp;
const byte *asn;
size_t mdlen, asnlen;
struct cmp_help_context_s *ctx = opaque;
PKT_signature *sig = ctx->sig;
MD_HANDLE digest = ctx->md;
old_enc = 0;
for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) {
if( !j ) {
if( !i && c != 1 )
break;
else if( i && c == 0xff )
; /* skip the padding */
else if( i && !c )
j++;
else
break;
}
else if( ++j == 18 && c != 1 )
break;
else if( j == 19 && c == 0 ) {
old_enc++;
break;
}
}
if( old_enc ) {
log_error("old encoding scheme is not supported\n");
return G10ERR_GENERAL;
}
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc; /* unsupported algo */
asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen );
for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0;
i++, j-- )
if( asn[j] != c )
break;
if( j != -1 || mpi_getbyte(result, i) )
return G10ERR_BAD_PUBKEY; /* ASN is wrong */
for(i++; (c=mpi_getbyte(result, i)) != -1; i++ )
if( c != 0xff )
break;
i++;
if( c != sig->digest_algo || mpi_getbyte(result, i) ) {
/* Padding or leading bytes in signature is wrong */
return G10ERR_BAD_PUBKEY;
}
if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0]
|| mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) {
/* Wrong key used to check the signature */
return G10ERR_BAD_PUBKEY;
}
dp = md_read( digest, sig->digest_algo );
for(i=mdlen-1; i >= 0; i--, dp++ ) {
if( mpi_getbyte( result, i ) != *dp )
return G10ERR_BAD_SIGN;
}
return 0;
#else
return -1;
#endif
}
static int
do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
{
MPI result = NULL;
int rc=0;
struct cmp_help_context_s ctx;
if( pkc->version == 4 && pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_info("this is a PGP generated "
@ -77,169 +158,56 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
if( pkc->timestamp > sig->timestamp )
return G10ERR_TIME_CONFLICT; /* pubkey newer that signature */
if( is_ELGAMAL(pkc->pubkey_algo) ) {
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave;
/* make sure the digest algo is enabled (in case of a detached
* signature */
md_enable( digest, sig->digest_algo );
/* complete the digest */
md_putc( digest, sig->sig_class );
{ u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
md_final( digest );
result = encode_md_value( digest, sig->digest_algo,
mpi_get_nbits(pkc->pkey[0]));
if( DBG_CIPHER )
log_mpidump("calc sig frame (elg): ", result);
rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey );
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc;
if( (rc=check_pubkey_algo(sig->pubkey_algo)) )
return rc;
/* make sure the digest algo is enabled (in case of a detached signature)*/
md_enable( digest, sig->digest_algo );
/* complete the digest */
if( sig->version >= 4 )
md_putc( digest, sig->version );
md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave;
/* make sure the digest algo is enabled (in case of a detached
* signature */
md_enable( digest, sig->digest_algo );
/* complete the digest */
if( sig->version >= 4 )
md_putc( digest, sig->version );
md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( digest, sig->pubkey_algo );
md_putc( digest, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( digest, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( digest, buf, 6 );
}
md_final( digest );
result = mpi_alloc( (md_digest_length(sig->digest_algo)
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
mpi_set_buffer( result, md_read(digest, sig->digest_algo),
md_digest_length(sig->digest_algo), 0 );
if( DBG_CIPHER )
log_mpidump("calc sig frame: ", result);
rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey );
}
#if 0 /* WORK!!! */
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA
|| pkc->pubkey_algo == PUBKEY_ALGO_RSA_S ) {
int i, j, c, old_enc;
byte *dp;
const byte *asn;
size_t mdlen, asnlen;
result = mpi_alloc(40);
rsa_public( result, sig->d.rsa.rsa_integer, &pkc->d.rsa );
old_enc = 0;
for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) {
if( !j ) {
if( !i && c != 1 )
break;
else if( i && c == 0xff )
; /* skip the padding */
else if( i && !c )
j++;
else
break;
}
else if( ++j == 18 && c != 1 )
break;
else if( j == 19 && c == 0 ) {
old_enc++;
break;
}
}
if( old_enc ) {
log_error("old encoding scheme is not supported\n");
rc = G10ERR_GENERAL;
goto leave;
}
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave; /* unsupported algo */
md_enable( digest, sig->digest_algo );
asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen );
for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0;
i++, j-- )
if( asn[j] != c )
break;
if( j != -1 || mpi_getbyte(result, i) ) { /* ASN is wrong */
rc = G10ERR_BAD_PUBKEY;
goto leave;
}
for(i++; (c=mpi_getbyte(result, i)) != -1; i++ )
if( c != 0xff )
break;
i++;
if( c != sig->digest_algo || mpi_getbyte(result, i) ) {
/* Padding or leading bytes in signature is wrong */
rc = G10ERR_BAD_PUBKEY;
goto leave;
}
if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0]
|| mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) {
/* Wrong key used to check the signature */
rc = G10ERR_BAD_PUBKEY;
goto leave;
}
/* complete the digest */
md_putc( digest, sig->sig_class );
{ u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
md_final( digest );
dp = md_read( digest, sig->digest_algo );
for(i=mdlen-1; i >= 0; i--, dp++ ) {
if( mpi_getbyte( result, i ) != *dp ) {
rc = G10ERR_BAD_SIGN;
goto leave;
}
}
}
#endif
else {
/*log_debug("signature_check: unsupported pubkey algo %d\n",
pkc->pubkey_algo );*/
rc = G10ERR_PUBKEY_ALGO;
goto leave;
byte buf[6];
size_t n;
md_putc( digest, sig->pubkey_algo );
md_putc( digest, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( digest, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( digest, buf, 6 );
}
md_final( digest );
leave:
result = encode_md_value( pkc->pubkey_algo, digest, sig->digest_algo,
mpi_get_nbits(pkc->pkey[0]));
ctx.sig = sig;
ctx.md = digest;
rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey,
cmp_help, &ctx );
mpi_free( result );
return rc;
}

View file

@ -53,14 +53,8 @@ do_sign( PKT_secret_cert *skc, PKT_signature *sig,
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
frame = mpi_alloc( (md_digest_length(digest_algo)+BYTES_PER_MPI_LIMB-1)
/ BYTES_PER_MPI_LIMB );
mpi_set_buffer( frame, md_read(md, digest_algo),
md_digest_length(digest_algo), 0 );
}
else
frame = encode_md_value( md, digest_algo, mpi_get_nbits(skc->skey[0]));
frame = encode_md_value( skc->pubkey_algo, md,
digest_algo, mpi_get_nbits(skc->skey[0]));
rc = pubkey_sign( skc->pubkey_algo, sig->data, frame, skc->skey );
mpi_free(frame);
if( rc )