1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

* sign.c (hash_for, sign_file): When encrypting and signing at the same

time, consult the various hash prefs to pick a hash algorithm to use.
Pass in a 160-bit hint if any of the signing keys are DSA.

* keydb.h, pkclist.c (select_algo_from_prefs, algo_available): Pass a
"hints" opaque pointer in to let the caller give hints as to what
algorithms would be acceptable.  The only current hint is for
PREFTYPE_HASH to require a 160-bit hash for DSA.  Change all callers in
encode.c (encode_crypt, encrypt_filter) and sign.c (sign_file).  If we
settle on MD5 as the best algorithm based solely on recepient keys and
SHA1 is also a possibility, use SHA1 unless the user intentionally chose
MD5.  This is as per 2440:13.

* exec.c (make_tempdir): Fix duplicated filename problem.
This commit is contained in:
David Shaw 2002-06-04 23:18:37 +00:00
parent ae02cf4630
commit fd08b13528
6 changed files with 115 additions and 20 deletions

View File

@ -1,3 +1,21 @@
2002-06-04 David Shaw <dshaw@jabberwocky.com>
* sign.c (hash_for, sign_file): When encrypting and signing at the
same time, consult the various hash prefs to pick a hash algorithm
to use. Pass in a 160-bit hint if any of the signing keys are
DSA.
* keydb.h, pkclist.c (select_algo_from_prefs, algo_available):
Pass a "hints" opaque pointer in to let the caller give hints as
to what algorithms would be acceptable. The only current hint is
for PREFTYPE_HASH to require a 160-bit hash for DSA. Change all
callers in encode.c (encode_crypt, encrypt_filter) and sign.c
(sign_file). If we settle on MD5 as the best algorithm based
solely on recepient keys and SHA1 is also a possibility, use SHA1
unless the user intentionally chose MD5. This is as per 2440:13.
* exec.c (make_tempdir): Fix duplicated filename problem.
2002-06-03 David Shaw <dshaw@jabberwocky.com>
* packet.h, parse-packet.c (enum_sig_subpkt): Report back from

View File

@ -336,7 +336,7 @@ encode_crypt( const char *filename, STRLIST remusr )
/* create a session key */
cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek);
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM, NULL );
/* The only way select_algo_from_prefs can fail here is when
mixing v3 and v4 keys, as v4 keys have an implicit
preference entry for 3DES, and the pk_list cannot be empty.
@ -415,7 +415,8 @@ encode_crypt( const char *filename, STRLIST remusr )
if(compr_algo==-1)
{
if((compr_algo=select_algo_from_prefs( pk_list, PREFTYPE_ZIP))==-1)
if((compr_algo=
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,NULL))==-1)
compr_algo=DEFAULT_COMPRESS_ALGO;
}
@ -485,7 +486,7 @@ encrypt_filter( void *opaque, int control,
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
efx->cfx.dek->algo =
select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM, NULL );
if( efx->cfx.dek->algo == -1 ) {
/* because 3DES is implicitly in the prefs, this can only
* happen if we do not have any public keys in the list */

View File

@ -93,10 +93,12 @@ static int win_system(const char *command)
/* Makes a temp directory and filenames */
static int make_tempdir(struct exec_info *info)
{
char *tmp=opt.temp_dir,*name=info->name;
char *tmp=opt.temp_dir,*namein=info->name,*nameout;
if(!name)
name=info->binary?"tempfile" EXTSEP_S "bin":"tempfile" EXTSEP_S "txt";
if(!namein)
namein=info->binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
/* Make up the temp dir and files in case we need them */
@ -151,14 +153,14 @@ static int make_tempdir(struct exec_info *info)
info->madedir=1;
info->tempfile_in=m_alloc(strlen(info->tempdir)+
strlen(DIRSEP_S)+strlen(name)+1);
sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,name);
strlen(DIRSEP_S)+strlen(namein)+1);
sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
if(!info->writeonly)
{
info->tempfile_out=m_alloc(strlen(info->tempdir)+
strlen(DIRSEP_S)+strlen(name)+1);
sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,name);
strlen(DIRSEP_S)+strlen(nameout)+1);
sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
}
}

View File

@ -166,7 +166,7 @@ void show_revocation_reason( PKT_public_key *pk, int mode );
int check_signatures_trust( PKT_signature *sig );
void release_pk_list( PK_LIST pk_list );
int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use );
int select_algo_from_prefs( PK_LIST pk_list, int preftype );
int select_algo_from_prefs( PK_LIST pk_list, int preftype, void *hint );
int select_mdc_from_pklist (PK_LIST pk_list);
/*-- skclist.c --*/

View File

@ -970,7 +970,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
such a broken preference list, so I'm including it. -dms */
static int
algo_available( int preftype, int algo )
algo_available( int preftype, int algo, void *hint )
{
if( preftype == PREFTYPE_SYM ) {
if( opt.pgp6 && ( algo != 1 && algo != 2 && algo != 3) )
@ -983,6 +983,14 @@ algo_available( int preftype, int algo )
return algo && !check_cipher_algo( algo );
}
else if( preftype == PREFTYPE_HASH ) {
int bits=0;
if(hint)
bits=*(int *)hint;
if(bits && (bits != md_digest_length(algo)))
return 0;
if( (opt.pgp6 || opt.pgp7 ) && ( algo != 1 && algo != 2 && algo != 3) )
return 0;
@ -1004,7 +1012,7 @@ algo_available( int preftype, int algo )
* Return -1 if we could not find an algorithm.
*/
int
select_algo_from_prefs( PK_LIST pk_list, int preftype )
select_algo_from_prefs( PK_LIST pk_list, int preftype, void *hint )
{
PK_LIST pkr;
u32 bits[8];
@ -1022,9 +1030,9 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
memset( mask, 0, 8 * sizeof *mask );
if( preftype == PREFTYPE_SYM ) {
if( pkr->pk->version < 4 &&
pkr->pk->selfsigversion < 4 &&
opt.pgp2 )
if( opt.pgp2 &&
pkr->pk->version < 4 &&
pkr->pk->selfsigversion < 4 )
mask[0] |= (1<<1); /* IDEA is implicitly there for v3 keys
with v3 selfsigs (rfc2440:12.1) if
--pgp2 mode is on. This doesn't
@ -1033,6 +1041,21 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
else
mask[0] |= (1<<2); /* 3DES is implicitly there for everyone else */
}
else if( preftype == PREFTYPE_HASH ) {
/* While I am including this code for completeness, note
that currently --pgp2 mode locks the hash at MD5, so this
function will never even be called. Even if the hash
wasn't locked at MD5, we don't support sign+encrypt in
--pgp2 mode, and that's the only time PREFTYPE_HASH is
used anyway. -dms */
if( opt.pgp2 &&
pkr->pk->version < 4 &&
pkr->pk->selfsigversion < 4 )
mask[0] |= (1<<1); /* MD5 is there for v3 keys with v3
selfsigs when --pgp2 is on. */
else
mask[0] |= (1<<2); /* SHA1 is there for everyone else */
}
else if( preftype == PREFTYPE_ZIP )
mask[0] |= (1<<0); /* Uncompressed is implicit */
@ -1086,7 +1109,7 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
for(j=0; prefs[j].type; j++ ) {
if( prefs[j].type == preftype ) {
if( (bits[prefs[j].value/32] & (1<<(prefs[j].value%32))) ) {
if( algo_available( preftype, prefs[j].value ) ) {
if( algo_available( preftype, prefs[j].value, hint ) ) {
any = 1;
i = prefs[j].value;
break;
@ -1098,7 +1121,7 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
if( !prefs || !any ) {
for(j=0; j < 256; j++ )
if( (bits[j/32] & (1<<(j%32))) ) {
if( algo_available( preftype, j ) ) {
if( algo_available( preftype, j, hint ) ) {
i = j;
break;
}
@ -1115,6 +1138,29 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
i = 1; /* yep; we can use compression algo 1 */
}
/* "If you are building an authentication system, the recipient
may specify a preferred signing algorithm. However, the signer
would be foolish to use a weak algorithm simply because the
recipient requests it." RFC2440:13. If we settle on MD5, and
SHA1 is also available, use SHA1 instead. Of course, if the
user intentinally chose MD5 (by putting it in their personal
prefs), then we should do what they say. */
if(preftype==PREFTYPE_HASH &&
i==DIGEST_ALGO_MD5 && (bits[0] & (1<<DIGEST_ALGO_SHA1)))
{
i=DIGEST_ALGO_SHA1;
if(opt.personal_prefs)
for(j=0; prefs[j].type; j++ )
if(opt.personal_prefs[j].type==PREFTYPE_HASH &&
opt.personal_prefs[j].value==DIGEST_ALGO_MD5)
{
i=DIGEST_ALGO_MD5;
break;
}
}
return i;
}
@ -1138,7 +1184,7 @@ select_mdc_from_pklist (PK_LIST pk_list)
else
mdc = pkr->pk->mdc_feature;
if (!mdc)
return 0; /* at least on recipeint does not support it */
return 0; /* at least one recipient does not support it */
}
return 1; /* can be used */
}

View File

@ -49,6 +49,8 @@
#define LF "\n"
#endif
static int recipient_digest_algo=0;
/****************
* Create a notation. It is assumed that the stings in STRLIST
* are already checked to contain only printable data and have a valid
@ -332,6 +334,8 @@ hash_for(int pubkey_algo, int packet_version )
{
if( opt.def_digest_algo )
return opt.def_digest_algo;
if( recipient_digest_algo )
return recipient_digest_algo;
if( pubkey_algo == PUBKEY_ALGO_DSA )
return DIGEST_ALGO_SHA1;
if( pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 )
@ -673,6 +677,28 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
iobuf_push_filter( inp, text_filter, &tfx );
mfx.md = md_open(0, 0);
/* If we're encrypting and signing, it is reasonable to pick the
hash algorithm to use out of the recepient key prefs. */
if(pk_list && !opt.def_digest_algo)
{
int hashlen=0,algo;
/* Of course, if the recipient asks for something unreasonable
(like a non-160-bit hash for DSA, for example), then don't
do it. Check all sk's - if any are DSA, then the hash must
be 160-bit. In the future this can be more complex with
different hashes for each sk, but so long as there is only
one signing algorithm with hash restrictions, this is
ok. -dms */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA)
hashlen=20;
if((algo=select_algo_from_prefs(pk_list,PREFTYPE_HASH,&hashlen))>0)
recipient_digest_algo=algo;
}
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version ));
@ -707,7 +733,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
Still, if it did fail, we'll also end up with the
default. */
if((compr_algo=select_algo_from_prefs( pk_list, PREFTYPE_ZIP))==-1)
if((compr_algo=
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,NULL))==-1)
compr_algo=DEFAULT_COMPRESS_ALGO;
}
@ -788,6 +815,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
md_close( mfx.md );
release_sk_list( sk_list );
release_pk_list( pk_list );
recipient_digest_algo=0;
return rc;
}