gpg: Remove all support for v3 keys and always create v4-signatures.

* g10/build-packet.c (do_key): Remove support for building v3 keys.
* g10/parse-packet.c (read_protected_v3_mpi): Remove.
(parse_key): Remove support for v3-keys.  Add dedicated warnings for
v3-key packets.
* g10/keyid.c (hash_public_key): Remove v3-key support.
(keyid_from_pk): Ditto.
(fingerprint_from_pk): Ditto.

* g10/options.h (opt): Remove fields force_v3_sigs and force_v4_certs.
* g10/gpg.c (cmd_and_opt_values): Remove oForceV3Sigs, oNoForceV3Sigs,
oForceV4Certs, oNoForceV4Certs.
(opts): Turn --force-v3-sigs, --no-force-v3-sigs, --force-v4-certs,
--no-force-v4-certs int dummy options.
(main): Remove setting of the force_v3_sigs force_v4_certs flags.
* g10/revoke.c (gen_revoke, create_revocation): Always create v4 certs.
* g10/sign.c (hash_uid): Remove support for v3-signatures
(hash_sigversion_to_magic): Ditto.
(only_old_style): Remove this v3-key function.
(write_signature_packets): Remove support for creating v3-signatures.
(sign_file): Ditto.
(sign_symencrypt_file): Ditto.
(clearsign_file): Ditto.  Remove code to emit no Hash armor line if
only v3-keys are used.
(make_keysig_packet): Remove arg SIGVERSION and force using
v4-signatures.  Change all callers to not pass a value for this arg.
Remove all v3-key related code.
(update_keysig_packet): Remove v3-signature support.
* g10/keyedit.c (sign_uids): Always create v4-signatures.

* g10/textfilter.c (copy_clearsig_text): Remove arg pgp2mode and
change caller.
--

v3 keys are deprecated for about 15 years and due the severe
weaknesses of MD5 it does not make any sense to keep code around to
use these old and broken keys.  Users who need to decrypt old messages
should use gpg 1.4 and best re-encrypt them to modern standards.
verification of old (i.e. PGP2) created signatures is thus also not
anymore possible but such signatures have no values anyway - MD5 is
just too broken.

We have also kept support for v3 signatures until now.  With the
removal of support for v3 keys it is questionable whether it makes any
sense to keep support for v3-signatures.  What we do now is to keep
support for verification of v3-signatures but we force the use of
v4-signatures.  The latter makes the --pgp6 and --pgp7 switch a bit
obsolete because those PGP versions require v3-signatures for
messages.  These versions of PGP are also really old and not anymore
maintained so they have not received any bug fixes and should not be
used anyway.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2014-10-12 20:07:12 +02:00
parent 60d22d54a5
commit 8fd150b05b
15 changed files with 222 additions and 476 deletions

View File

@ -9,6 +9,15 @@
===================
GnuPG (>=1.0.3) is in compliance with RFC2440 despite these exceptions:
* With GnuPG >= 2.1.0 all support for version 3 keys has been
removed. Thus there is no more compatibility with PGP-2. Users
who need to be able to decrypt old PGP 2 messages should use
GnuPG 1.4.x along with the option --allow-weak-digest-algos.
* With GnuPG >= 2.1.0 all signatures (on messages and keys) are
created using version 4 signatures. Support for verifying
version 3 signature is still available.
* (9.2) states that IDEA SHOULD be implemented. This is not done
due to patent problems.
UPDATE: Since version 1.4.13 (or GnuPG 2.x with Libgcrypt 1.6)

View File

@ -2129,6 +2129,7 @@ platforms that have different line ending conventions (UNIX-like to Mac,
Mac to Windows, etc). @option{--no-textmode} disables this option, and
is the default.
@ifclear gpgtwoone
@item --force-v3-sigs
@itemx --no-force-v3-sigs
@opindex force-v3-sigs
@ -2147,6 +2148,15 @@ Defaults to no.
Always use v4 key signatures even on v3 keys. This option also
changes the default hash algorithm for v3 RSA keys from MD5 to SHA-1.
@option{--no-force-v4-certs} disables this option.
@end ifclear
@ifset gpgtwoone
@item --force-v3-sigs
@itemx --no-force-v3-sigs
@item --force-v4-certs
@itemx --no-force-v4-certs
These options are obsolete and have no effect since GnuPG 2.1.
@end ifset
@item --force-mdc
@opindex force-mdc
@ -2301,8 +2311,12 @@ compression algorithms none and ZIP. This also disables
--throw-keyids, and making signatures with signing subkeys as PGP 6
does not understand signatures made by signing subkeys.
This option implies @option{--disable-mdc --escape-from-lines
--force-v3-sigs}.
@ifclear gpgtwoone
This option implies @option{--disable-mdc --escape-from-lines --force-v3-sigs}.
@end ifclear
@ifset gpgtwoone
This option implies @option{--disable-mdc --escape-from-lines}.
@end ifset
@item --pgp7
@opindex pgp7

View File

@ -291,24 +291,13 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
int i, nskey, npkey;
iobuf_t 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 4 */
if ( !pk->version )
iobuf_put ( a, 3 );
iobuf_put ( a, 4 );
else
iobuf_put ( a, pk->version );
write_32 (a, pk->timestamp );
/* v3 needs the expiration time. */
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 );
/* Get number of secret and public parameters. They are held in one
@ -347,45 +336,37 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
/* Build the header for protected (encrypted) secret parameters. */
if (ski->is_protected)
{
if ( is_RSA (pk->pubkey_algo) && pk->version < 4 && !ski->s2k.mode )
/* OpenPGP protection according to rfc2440. */
iobuf_put (a, ski->sha1chk? 0xfe : 0xff);
iobuf_put (a, ski->algo);
if (ski->s2k.mode >= 1000)
{
/* The simple rfc1991 (v3) way. */
iobuf_put (a, ski->algo );
iobuf_write (a, ski->iv, ski->ivlen);
/* These modes are not possible in OpenPGP, we use them
to implement our extensions, 101 can be viewed 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, ski->s2k.hash_algo);
iobuf_write (a, "GNU", 3 );
iobuf_put (a, ski->s2k.mode - 1000);
}
else
{
/* OpenPGP protection according to rfc2440. */
iobuf_put (a, ski->sha1chk? 0xfe : 0xff);
iobuf_put (a, ski->algo);
if (ski->s2k.mode >= 1000)
{
/* These modes are not possible in OpenPGP, we use
them to implement our extensions, 101 can be
viewed 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, ski->s2k.hash_algo);
iobuf_write (a, "GNU", 3 );
iobuf_put (a, ski->s2k.mode - 1000);
}
else
{
iobuf_put (a, ski->s2k.mode);
iobuf_put (a, ski->s2k.hash_algo);
}
if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
iobuf_write (a, ski->s2k.salt, 8);
if (ski->s2k.mode == 3)
iobuf_put (a, ski->s2k.count);
/* For our special modes 1001, 1002 we do not need an IV. */
if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
iobuf_write (a, ski->iv, ski->ivlen);
iobuf_put (a, ski->s2k.mode);
iobuf_put (a, ski->s2k.hash_algo);
}
if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
iobuf_write (a, ski->s2k.salt, 8);
if (ski->s2k.mode == 3)
iobuf_put (a, ski->s2k.count);
/* For our special modes 1001, 1002 we do not need an IV. */
if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
iobuf_write (a, ski->iv, ski->ivlen);
}
else /* Not protected. */
iobuf_put (a, 0 );
@ -400,7 +381,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
/* The serial number gets stored in the IV field. */
iobuf_write (a, ski->iv, ski->ivlen);
}
else if (ski->is_protected && pk->version >= 4)
else if (ski->is_protected)
{
/* The secret key is protected - write it out as it is. */
byte *p;
@ -410,20 +391,6 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8 );
}
else if (ski->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 (pk->pkey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (pk->pkey[i], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8);
}
write_16 (a, ski->csum );
}
else
{
/* Non-protected key. */

View File

@ -152,7 +152,7 @@ int cipher_filter( void *opaque, int control,
int text_filter( void *opaque, int control,
iobuf_t chain, byte *buf, size_t *ret_len);
int copy_clearsig_text (iobuf_t out, iobuf_t inp, gcry_md_hd_t md,
int escape_dash, int escape_from, int pgp2mode);
int escape_dash, int escape_from);
/*-- progress.c --*/
progress_filter_context_t *new_progress_context (void);

View File

@ -272,10 +272,6 @@ enum cmd_and_opt_values
oShowPhotos,
oNoShowPhotos,
oPhotoViewer,
oForceV3Sigs,
oNoForceV3Sigs,
oForceV4Certs,
oNoForceV4Certs,
oForceMDC,
oNoForceMDC,
oDisableMDC,
@ -525,10 +521,6 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oQuiet, "quiet", "@"),
ARGPARSE_s_n (oNoTTY, "no-tty", "@"),
ARGPARSE_s_n (oForceV3Sigs, "force-v3-sigs", "@"),
ARGPARSE_s_n (oNoForceV3Sigs, "no-force-v3-sigs", "@"),
ARGPARSE_s_n (oForceV4Certs, "force-v4-certs", "@"),
ARGPARSE_s_n (oNoForceV4Certs, "no-force-v4-certs", "@"),
ARGPARSE_s_n (oForceMDC, "force-mdc", "@"),
ARGPARSE_s_n (oNoForceMDC, "no-force-mdc", "@"),
ARGPARSE_s_n (oDisableMDC, "disable-mdc", "@"),
@ -810,6 +802,10 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoop, "no-sk-comments", "@"),
ARGPARSE_s_n (oNoop, "compress-keys", "@"),
ARGPARSE_s_n (oNoop, "compress-sigs", "@"),
ARGPARSE_s_n (oNoop, "force-v3-sigs", "@"),
ARGPARSE_s_n (oNoop, "no-force-v3-sigs", "@"),
ARGPARSE_s_n (oNoop, "force-v4-certs", "@"),
ARGPARSE_s_n (oNoop, "no-force-v4-certs", "@"),
ARGPARSE_end ()
};
@ -2535,7 +2531,6 @@ main (int argc, char **argv)
opt.allow_freeform_uid = 1;
opt.pgp2_workarounds = 0;
opt.escape_from = 1;
opt.force_v3_sigs = 0;
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
opt.def_digest_algo = 0;
@ -2553,7 +2548,6 @@ main (int argc, char **argv)
opt.allow_freeform_uid = 1;
opt.pgp2_workarounds = 0;
opt.escape_from = 0;
opt.force_v3_sigs = 0;
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
opt.def_digest_algo = 0;
@ -2637,10 +2631,7 @@ main (int argc, char **argv)
opt.verify_options&=~VERIFY_SHOW_PHOTOS;
break;
case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
case oForceV3Sigs: opt.force_v3_sigs = 1; break;
case oNoForceV3Sigs: opt.force_v3_sigs = 0; break;
case oForceV4Certs: opt.force_v4_certs = 1; break;
case oNoForceV4Certs: opt.force_v4_certs = 0; break;
case oForceMDC: opt.force_mdc = 1; break;
case oNoForceMDC: opt.force_mdc = 0; break;
case oDisableMDC: opt.disable_mdc = 1; break;
@ -3288,15 +3279,17 @@ main (int argc, char **argv)
/* Do these after the switch(), so they can override settings. */
if(PGP6)
{
/* That does not anymore work becuase we have no more support
for v3 signatures. */
opt.disable_mdc=1;
opt.escape_from=1;
opt.force_v3_sigs=1;
opt.ask_sig_expire=0;
}
else if(PGP7)
{
/* That does not anymore work because we have no more support
for v3 signatures. */
opt.escape_from=1;
opt.force_v3_sigs=1;
opt.ask_sig_expire=0;
}
else if(PGP8)

View File

@ -536,14 +536,10 @@ sign_uids (estream_t fp,
{
u32 sk_keyid[2], pk_keyid[2];
char *p, *trust_regexp = NULL;
int force_v4 = 0, class = 0, selfsig = 0;
int class = 0, selfsig = 0;
u32 duration = 0, timestamp = 0;
byte trust_depth = 0, trust_value = 0;
if (local || nonrevocable || trust
|| opt.cert_policy_url || opt.cert_notations)
force_v4 = 1;
pk = sk_rover->pk;
keyid_from_pk (pk, sk_keyid);
@ -567,14 +563,7 @@ sign_uids (estream_t fp,
/* Is this a self-sig? */
if (pk_keyid[0] == sk_keyid[0] && pk_keyid[1] == sk_keyid[1])
{
selfsig = 1;
/* Do not force a v4 sig here, otherwise it would
be difficult to remake a v3 selfsig. If this
is a v3->v4 promotion case, then we set
force_v4 later anyway. */
force_v4 = 0;
}
selfsig = 1;
}
else if (node->pkt->pkttype == PKT_USER_ID)
{
@ -716,7 +705,6 @@ sign_uids (estream_t fp,
"it to an OpenPGP self-"
"signature? (y/N) ")))
{
force_v4 = 1;
node->flag |= NODFLG_DELSIG;
xfree (user);
continue;
@ -860,7 +848,6 @@ sign_uids (estream_t fp,
passphrase, etc). */
timestamp = now;
duration = primary_pk->expiredate - now;
force_v4 = 1;
}
cpr_kill_prompt ();
@ -879,9 +866,6 @@ sign_uids (estream_t fp,
duration = parse_expire_string (opt.def_cert_expire);
}
if (duration)
force_v4 = 1;
if (selfsig)
;
else
@ -1041,7 +1025,7 @@ sign_uids (estream_t fp,
node->pkt->pkt.user_id,
NULL,
pk,
0x13, 0, force_v4 ? 4 : 0, 0, 0,
0x13, 0, 0, 0,
keygen_add_std_prefs, primary_pk,
NULL);
else
@ -1049,7 +1033,7 @@ sign_uids (estream_t fp,
node->pkt->pkt.user_id,
NULL,
pk,
class, 0, force_v4 ? 4 : 0,
class, 0,
timestamp, duration,
sign_mk_attrib, &attrib,
NULL);
@ -3290,7 +3274,7 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
if (!uid)
return 0;
err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0, 0,
err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
keygen_add_std_prefs, pk, NULL);
if (err)
{
@ -3674,9 +3658,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
break;
}
/* The 1F signature must be at least v4 to carry the revocation key
subpacket. */
rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 4, 0, 0,
rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
keygen_add_revkey, &revkey, NULL);
if (rc)
{
@ -4966,7 +4948,7 @@ reloop: /* (must use this, because we are modifing the list) */
}
rc = make_keysig_packet (&sig, primary_pk,
unode->pkt->pkt.user_id,
NULL, signerkey, 0x30, 0, 0, 0, 0,
NULL, signerkey, 0x30, 0, 0, 0,
sign_mk_attrib, &attrib, NULL);
free_public_key (signerkey);
if (rc)
@ -5058,7 +5040,7 @@ menu_revuid (KBNODE pub_keyblock)
node->flag &= ~NODFLG_SELUID;
rc = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x30, 0,
(reason == NULL) ? 3 : 0, timestamp, 0,
timestamp, 0,
sign_mk_attrib, &attrib, NULL);
if (rc)
{
@ -5122,7 +5104,7 @@ menu_revkey (KBNODE pub_keyblock)
return 0;
rc = make_keysig_packet (&sig, pk, NULL, NULL, pk,
0x20, 0, opt.force_v4_certs ? 4 : 0, 0, 0,
0x20, 0, 0, 0,
revocation_reason_build_cb, reason, NULL);
if (rc)
{
@ -5183,7 +5165,7 @@ menu_revsubkey (KBNODE pub_keyblock)
node->flag &= ~NODFLG_SELKEY;
rc = make_keysig_packet (&sig, mainpk, NULL, subpk, mainpk,
0x28, 0, 0, 0, 0, sign_mk_attrib, &attrib,
0x28, 0, 0, 0, sign_mk_attrib, &attrib,
NULL);
if (rc)
{

View File

@ -812,7 +812,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
cache_public_key (sub_pk);
err = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_psk, 0x19,
0, 0, timestamp, 0, NULL, NULL, cache_nonce);
0, timestamp, 0, NULL, NULL, cache_nonce);
if (err)
log_error ("make_keysig_packet failed for backsig: %s\n", g10_errstr(err));
else
@ -922,7 +922,7 @@ write_direct_sig (KBNODE root, PKT_public_key *psk,
/* Make the signature. */
err = make_keysig_packet (&sig, pk, NULL,NULL, psk, 0x1F,
0, 0, timestamp, 0,
0, timestamp, 0,
keygen_add_revkey, revkey, cache_nonce);
if (err)
{
@ -977,7 +977,7 @@ write_selfsigs (KBNODE root, PKT_public_key *psk,
/* Make the signature. */
err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13,
0, 0, timestamp, 0,
0, timestamp, 0,
keygen_add_std_prefs, pk, cache_nonce);
if (err)
{
@ -1036,12 +1036,12 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
oduap.usage = use;
oduap.pk = sub_pk;
err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
0, 0, timestamp, 0,
0, timestamp, 0,
keygen_add_key_flags_and_expire, &oduap,
cache_nonce);
if (err)
{
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
log_error ("make_keysig_packeto failed: %s\n", g10_errstr (err));
return err;
}

View File

@ -147,10 +147,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
size_t nbytes;
int npkey = pubkey_get_npkey (pk->pubkey_algo);
/* Two extra bytes for the expiration date in v3 */
if(pk->version<4)
n+=2;
/* FIXME: We can avoid the extra malloc by calling only the first
mpi_print here which computes the required length and calling the
real mpi_print only at the end. The speed advantage would only be
@ -211,16 +207,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
gcry_md_putc ( md, pk->timestamp >> 8 );
gcry_md_putc ( md, pk->timestamp );
if(pk->version<4)
{
u16 days=0;
if(pk->expiredate)
days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
gcry_md_putc ( md, days >> 8 );
gcry_md_putc ( md, days );
}
gcry_md_putc ( md, pk->pubkey_algo );
if(npkey==0 && pk->pkey[0]
@ -432,18 +418,6 @@ keyid_from_pk (PKT_public_key *pk, u32 *keyid)
keyid[1] = pk->keyid[1];
lowbits = keyid[1];
}
else if( pk->version < 4 )
{
if( is_RSA(pk->pubkey_algo) )
{
lowbits = (pubkey_get_npkey (pk->pubkey_algo) ?
v3_keyid ( pk->pkey[0], keyid ) : 0); /* From n. */
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
else
pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
else
{
const byte *dp;
@ -706,66 +680,20 @@ colon_expirestr_from_sig (PKT_signature *sig)
byte *
fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
{
byte *buf;
const byte *dp;
size_t len, nbytes;
int i;
size_t len;
gcry_md_hd_t md;
if ( pk->version < 4 )
{
if ( is_RSA(pk->pubkey_algo) )
{
/* RSA in version 3 packets is special. */
gcry_md_hd_t md;
if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
BUG ();
if ( pubkey_get_npkey (pk->pubkey_algo) > 1 )
{
for (i=0; i < 2; i++)
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
&nbytes, pk->pkey[i]))
BUG ();
/* fixme: Better allocate BUF on the stack */
buf = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
NULL, pk->pkey[i]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
}
}
gcry_md_final (md);
if (!array)
array = xmalloc (16);
len = 16;
memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
gcry_md_close(md);
}
else
{
if (!array)
array = xmalloc(16);
len = 16;
memset (array,0,16);
}
}
else
{
gcry_md_hd_t md;
md = do_fingerprint_md(pk);
dp = gcry_md_read( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
assert( len <= MAX_FINGERPRINT_LEN );
if (!array)
array = xmalloc ( len );
memcpy (array, dp, len );
pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
gcry_md_close( md);
}
md = do_fingerprint_md(pk);
dp = gcry_md_read( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
assert( len <= MAX_FINGERPRINT_LEN );
if (!array)
array = xmalloc ( len );
memcpy (array, dp, len );
pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
gcry_md_close( md);
if (ret_len)
*ret_len = len;

View File

@ -74,8 +74,6 @@ struct
int no_armor;
int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/
int def_cipher_algo;
int force_v3_sigs;
int force_v4_certs;
int force_mdc;
int disable_mdc;
int def_digest_algo;

View File

@ -530,7 +530,7 @@ int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2,
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
PKT_user_id *uid, PKT_public_key *subpk,
PKT_public_key *pksk, int sigclass, int digest_algo,
int sigversion, u32 timestamp, u32 duration,
u32 timestamp, u32 duration,
int (*mksubpkt)(PKT_signature *, void *),
void *opaque,
const char *cache_nonce);

View File

@ -1901,53 +1901,6 @@ parse_onepass_sig (IOBUF inp, int pkttype, unsigned long pktlen,
}
static gcry_mpi_t
read_protected_v3_mpi (IOBUF inp, unsigned long *length)
{
int c;
unsigned int nbits, nbytes;
unsigned char *buf, *p;
gcry_mpi_t val;
if (*length < 2)
{
log_error ("mpi too small\n");
return NULL;
}
if ((c = iobuf_get (inp)) == -1)
return NULL;
--*length;
nbits = c << 8;
if ((c = iobuf_get (inp)) == -1)
return NULL;
--*length;
nbits |= c;
if (nbits > 16384)
{
log_error ("mpi too large (%u bits)\n", nbits);
return NULL;
}
nbytes = (nbits + 7) / 8;
buf = p = xmalloc (2 + nbytes);
*p++ = nbits >> 8;
*p++ = nbits;
for (; nbytes && *length; nbytes--, --*length)
*p++ = iobuf_get (inp);
if (nbytes)
{
log_error ("packet shorter than mpi\n");
xfree (buf);
return NULL;
}
/* Convert buffer into an opaque MPI. */
val = gcry_mpi_set_opaque (NULL, buf, (p - buf) * 8);
return val;
}
static int
parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
byte * hdr, int hdrlen, PACKET * pkt)
@ -1956,7 +1909,6 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
int i, version, algorithm;
unsigned long timestamp, expiredate, max_expiredate;
int npkey, nskey;
int is_v4 = 0;
int rc = 0;
u32 keyid[2];
PKT_public_key *pk;
@ -1991,8 +1943,19 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
return 0;
}
else if (version == 4)
is_v4 = 1;
else if (version != 2 && version != 3)
{
/* The only supported version. Use an older gpg
versions (i.e. gpg 1.4 to parse v3 packets). */
}
else if (version == 2 || version == 3)
{
log_info ("packet(%d) with obsolete version %d\n", pkttype, version);
if (list_mode)
es_fprintf (listfp, ":key packet: [obsolete version %d]\n", version);
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
else
{
log_error ("packet(%d) with unknown version %d\n", pkttype, version);
if (list_mode)
@ -2012,23 +1975,8 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
timestamp = read_32 (inp);
pktlen -= 4;
if (is_v4)
{
expiredate = 0; /* have to get it from the selfsignature */
max_expiredate = 0;
}
else
{
unsigned short ndays;
ndays = read_16 (inp);
pktlen -= 2;
if (ndays)
expiredate = timestamp + ndays * 86400L;
else
expiredate = 0;
max_expiredate = expiredate;
}
expiredate = 0; /* have to get it from the selfsignature */
max_expiredate = 0;
algorithm = iobuf_get_noeof (inp);
pktlen--;
if (list_mode)
@ -2145,7 +2093,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
ski->s2k.hash_algo = iobuf_get_noeof (inp);
pktlen--;
/* Check for the special GNU extension. */
if (is_v4 && ski->s2k.mode == 101)
if (ski->s2k.mode == 101)
{
for (i = 0; i < 4 && pktlen; i++, pktlen--)
temp[i] = iobuf_get_noeof (inp);
@ -2312,7 +2260,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
10 * 8);
pktlen = 0;
}
else if (is_v4 && ski->is_protected)
else if (ski->is_protected)
{
/* Ugly: The length is encrypted too, so we read all stuff
* up to the end of the packet into the first SKEY
@ -2331,29 +2279,18 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
}
else
{
/* The v3 method: The mpi length is not encrypted. */
/* Not encrypted. */
for (i = npkey; i < nskey; i++)
{
if (ski->is_protected)
{
pk->pkey[i] = read_protected_v3_mpi (inp, &pktlen);
if (pk->pkey[i])
gcry_mpi_set_flag (pk->pkey[i], GCRYMPI_FLAG_USER1);
if (list_mode)
es_fprintf (listfp, "\tskey[%d]: [v3 protected]\n", i);
}
else
{
unsigned int n = pktlen;
pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
{
es_fprintf (listfp, "\tskey[%d]: ", i);
mpi_print (listfp, pk->pkey[i], mpi_print_mode);
es_putc ('\n', listfp);
}
}
unsigned int n = pktlen;
pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
{
es_fprintf (listfp, "\tskey[%d]: ", i);
mpi_print (listfp, pk->pkey[i], mpi_print_mode);
es_putc ('\n', listfp);
}
if (!pk->pkey[i])
err = gpg_error (GPG_ERR_INV_PACKET);

View File

@ -338,7 +338,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
/* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, pk2, 0x20, 0,
0, 0, 0,
0, 0,
revocation_reason_build_cb, reason,
NULL);
if( rc ) {
@ -465,7 +465,6 @@ create_revocation (const char *filename,
push_armor_filter (afx, out);
rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
opt.force_v4_certs? 4:0,
0, 0,
revocation_reason_build_cb, reason, cache_nonce);
if (rc)
@ -649,16 +648,13 @@ gen_revoke (const char *uname)
goto leave;
}
if (psk->version >= 4 || opt.force_v4_certs)
/* Get the reason for the revocation. */
reason = ask_revocation_reason (1, 0, 1);
if (!reason)
{
/* Get the reason for the revocation. */
reason = ask_revocation_reason (1, 0, 1);
if (!reason)
{
/* user decided to cancel */
rc = 0;
goto leave;
}
/* User decided to cancel. */
rc = 0;
goto leave;
}
if (!opt.armor)

View File

@ -155,30 +155,32 @@ mk_notation_policy_etc (PKT_signature *sig,
static void
hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid)
{
if ( sigversion >= 4 ) {
byte buf[5];
byte buf[5];
if(uid->attrib_data) {
buf[0] = 0xd1; /* indicates an attribute packet */
buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */
buf[2] = uid->attrib_len >> 16;
buf[3] = uid->attrib_len >> 8;
buf[4] = uid->attrib_len;
}
else {
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* always use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
}
gcry_md_write( md, buf, 5 );
(void)sigversion;
if (uid->attrib_data)
{
buf[0] = 0xd1; /* Indicates an attribute packet. */
buf[1] = uid->attrib_len >> 24; /* Always use 4 length bytes. */
buf[2] = uid->attrib_len >> 16;
buf[3] = uid->attrib_len >> 8;
buf[4] = uid->attrib_len;
}
else
{
buf[0] = 0xb4; /* Indicates a userid packet. */
buf[1] = uid->len >> 24; /* Always use 4 length bytes. */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
}
gcry_md_write( md, buf, 5 );
if(uid->attrib_data)
gcry_md_write (md, uid->attrib_data, uid->attrib_len );
else
gcry_md_write (md, uid->name, uid->len );
if (uid->attrib_data)
gcry_md_write (md, uid->attrib_data, uid->attrib_len );
else
gcry_md_write (md, uid->name, uid->len );
}
@ -188,45 +190,38 @@ hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid)
static void
hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
{
if (sig->version >= 4)
gcry_md_putc (md, sig->version);
gcry_md_putc (md, sig->sig_class);
if (sig->version < 4) {
u32 a = sig->timestamp;
gcry_md_putc (md, (a >> 24) & 0xff );
gcry_md_putc (md, (a >> 16) & 0xff );
gcry_md_putc (md, (a >> 8) & 0xff );
gcry_md_putc (md, a & 0xff );
}
else {
byte buf[6];
size_t n;
byte buf[6];
size_t n;
gcry_md_putc (md, sig->pubkey_algo);
gcry_md_putc (md, sig->digest_algo);
if (sig->hashed) {
n = sig->hashed->len;
gcry_md_putc (md, (n >> 8) );
gcry_md_putc (md, n );
gcry_md_write (md, sig->hashed->data, n );
n += 6;
}
else {
gcry_md_putc (md, 0); /* always hash the length of the subpacket*/
gcry_md_putc (md, 0);
n = 6;
}
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
gcry_md_write (md, buf, 6);
gcry_md_putc (md, sig->version);
gcry_md_putc (md, sig->sig_class);
gcry_md_putc (md, sig->pubkey_algo);
gcry_md_putc (md, sig->digest_algo);
if (sig->hashed)
{
n = sig->hashed->len;
gcry_md_putc (md, (n >> 8) );
gcry_md_putc (md, n );
gcry_md_write (md, sig->hashed->data, n );
n += 6;
}
else
{
gcry_md_putc (md, 0); /* Always hash the length of the subpacket. */
gcry_md_putc (md, 0);
n = 6;
}
/* Add some magic. */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* (n is only 16 bit, so this is always 0) */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
gcry_md_write (md, buf, 6);
}
/* Perform the sign operation. If CACHE_NONCE is given the agent is
advised to use that cached passphrase fro the key. */
static int
@ -520,26 +515,6 @@ hash_for (PKT_public_key *pk)
}
/* Return true iff all keys in SK_LIST are old style (v3 RSA). */
static int
only_old_style (SK_LIST sk_list)
{
SK_LIST sk_rover = NULL;
int old_style = 0;
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
{
PKT_public_key *pk = sk_rover->pk;
if (pk->pubkey_algo == PUBKEY_ALGO_RSA && pk->version < 4)
old_style = 1;
else
return 0;
}
return old_style;
}
static void
print_status_sig_created (PKT_public_key *pk, PKT_signature *sig, int what)
{
@ -705,10 +680,8 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
/* Build the signature packet. */
sig = xmalloc_clear (sizeof *sig);
if (opt.force_v3_sigs)
sig->version = 3;
else if (duration || opt.sig_policy_url
|| opt.sig_notations || opt.sig_keyserver_url)
if (duration || opt.sig_policy_url
|| opt.sig_notations || opt.sig_keyserver_url)
sig->version = 4;
else
sig->version = pk->version;
@ -727,11 +700,8 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
if (gcry_md_copy (&md, hash))
BUG ();
if (sig->version >= 4)
{
build_sig_subpkt_from_sig (sig);
mk_notation_policy_etc (sig, pk, NULL);
}
build_sig_subpkt_from_sig (sig);
mk_notation_policy_etc (sig, pk, NULL);
hash_sigversion_to_magic (md, sig);
gcry_md_final (md);
@ -814,13 +784,10 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
&& (rc=setup_symkey(&efx.symkey_s2k,&efx.symkey_dek)))
goto leave;
if(!opt.force_v3_sigs)
{
if(opt.ask_sig_expire && !opt.batch)
duration=ask_expire_interval(1,opt.def_sig_expire);
else
duration=parse_expire_string(opt.def_sig_expire);
}
if (opt.ask_sig_expire && !opt.batch)
duration = ask_expire_interval(1,opt.def_sig_expire);
else
duration = parse_expire_string(opt.def_sig_expire);
/* Note: In the old non-agent version the following call used to
unprotect the secret key. This is now done on demand by the agent. */
@ -1123,30 +1090,22 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
int rc = 0;
SK_LIST sk_list = NULL;
SK_LIST sk_rover = NULL;
int old_style = 0;
int only_md5 = 0;
u32 duration=0;
pfx = new_progress_context ();
afx = new_armor_context ();
init_packet( &pkt );
if(!opt.force_v3_sigs)
{
if(opt.ask_sig_expire && !opt.batch)
duration=ask_expire_interval(1,opt.def_sig_expire);
else
duration=parse_expire_string(opt.def_sig_expire);
}
if (opt.ask_sig_expire && !opt.batch)
duration = ask_expire_interval (1,opt.def_sig_expire);
else
duration = parse_expire_string (opt.def_sig_expire);
/* Note: In the old non-agent version the following call used to
unprotect the secret key. This is now done on demand by the agent. */
if( (rc=build_sk_list( locusr, &sk_list, PUBKEY_USAGE_SIG )) )
goto leave;
if(!duration )
old_style = only_old_style( sk_list );
/* prepare iobufs */
inp = iobuf_open(fname);
if (inp && is_secured_file (iobuf_get_fd (inp)))
@ -1184,18 +1143,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF );
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
{
if (hash_for (sk_rover->pk) == DIGEST_ALGO_MD5)
only_md5 = 1;
else
{
only_md5 = 0;
break;
}
}
if( !(old_style && only_md5) ) {
{
const char *s;
int any = 0;
byte hashs_seen[256];
@ -1234,8 +1182,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
if ( DBG_HASHING )
gcry_md_debug ( textmd, "clearsign" );
copy_clearsig_text( out, inp, textmd, !opt.not_dash_escaped,
opt.escape_from, (old_style && only_md5) );
copy_clearsig_text (out, inp, textmd, !opt.not_dash_escaped,
opt.escape_from);
/* fixme: check for read errors */
/* now write the armor */
@ -1292,13 +1240,10 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
memset( &cfx, 0, sizeof cfx);
init_packet( &pkt );
if(!opt.force_v3_sigs)
{
if(opt.ask_sig_expire && !opt.batch)
duration=ask_expire_interval(1,opt.def_sig_expire);
else
duration=parse_expire_string(opt.def_sig_expire);
}
if (opt.ask_sig_expire && !opt.batch)
duration = ask_expire_interval (1, opt.def_sig_expire);
else
duration = parse_expire_string (opt.def_sig_expire);
/* Note: In the old non-agent version the following call used to
unprotect the secret key. This is now done on demand by the agent. */
@ -1441,52 +1386,39 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
* applied (actually: dropped) when a v3 key is used. TIMESTAMP is
* the timestamp to use for the signature. 0 means "now" */
int
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
PKT_user_id *uid, PKT_public_key *subpk,
PKT_public_key *pksk,
int sigclass, int digest_algo,
int sigversion, u32 timestamp, u32 duration,
u32 timestamp, u32 duration,
int (*mksubpkt)(PKT_signature *, void *), void *opaque,
const char *cache_nonce)
{
PKT_signature *sig;
int rc=0;
int sigversion;
gcry_md_hd_t md;
assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
|| sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
|| sigclass == 0x30 || sigclass == 0x28 );
if (opt.force_v4_certs)
sigversion = 4;
sigversion = 4;
if (sigversion < pksk->version)
sigversion = pksk->version;
/* If you are making a signature on a v4 key using your v3 key, it
doesn't make sense to generate a v3 sig. After all, no v3-only
PGP implementation could understand the v4 key in the first
place. Note that this implies that a signature on an attribute
uid is usually going to be v4 as well, since they are not
generally found on v3 keys. */
if (sigversion < pk->version)
sigversion = pk->version;
if( !digest_algo )
{
/* Basically, this means use SHA1 always unless it's a v3 RSA
key making a v3 cert (use MD5), or the user specified
something (use whatever they said), or it's DSA (use the
best match). They still can't pick an inappropriate hash
for DSA or the signature will fail. Note that this still
allows the caller of make_keysig_packet to override the
user setting if it must. */
/* Basically, this means use SHA1 always unless the user
specified something (use whatever they said), or it's DSA
(use the best match). They still can't pick an
inappropriate hash for DSA or the signature will fail.
Note that this still allows the caller of
make_keysig_packet to override the user setting if it
must. */
if(opt.cert_digest_algo)
digest_algo=opt.cert_digest_algo;
else if(pksk->pubkey_algo == PUBKEY_ALGO_RSA
&& pk->version<4 && sigversion<4)
digest_algo = DIGEST_ALGO_MD5;
else if(pksk->pubkey_algo == PUBKEY_ALGO_DSA)
digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
@ -1533,16 +1465,14 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
if(duration)
sig->expiredate=sig->timestamp+duration;
sig->sig_class = sigclass;
if( sig->version >= 4 )
{
build_sig_subpkt_from_sig( sig );
mk_notation_policy_etc (sig, pk, pksk);
}
build_sig_subpkt_from_sig( sig );
mk_notation_policy_etc (sig, pk, pksk);
/* Crucial that the call to mksubpkt comes LAST before the calls
to finalize the sig as that makes it possible for the mksubpkt
function to get a reliable pointer to the subpacket area. */
if( sig->version >= 4 && mksubpkt )
if (mksubpkt)
rc = (*mksubpkt)( sig, opaque );
if( !rc ) {
@ -1627,17 +1557,14 @@ update_keysig_packet( PKT_signature **ret_sig,
duration of 1) since build-packet.c:build_sig_subpkt_from_sig
detects this case. */
if( sig->version >= 4 )
{
/* Put the updated timestamp into the sig. Note that this
will automagically lower any sig expiration dates to
correctly correspond to the differences in the timestamps
(i.e. the duration will shrink). */
build_sig_subpkt_from_sig( sig );
/* Put the updated timestamp into the sig. Note that this will
automagically lower any sig expiration dates to correctly
correspond to the differences in the timestamps (i.e. the
duration will shrink). */
build_sig_subpkt_from_sig( sig );
if (mksubpkt)
rc = (*mksubpkt)(sig, opaque);
}
if (mksubpkt)
rc = (*mksubpkt)(sig, opaque);
if (!rc) {
hash_sigversion_to_magic (md, sig);

View File

@ -161,7 +161,7 @@ text_filter( void *opaque, int control,
*/
int
copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
int escape_dash, int escape_from, int pgp2mode )
int escape_dash, int escape_from)
{
unsigned int maxlen;
byte *buffer = NULL; /* malloced buffer */
@ -170,10 +170,7 @@ copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
int truncated = 0;
int pending_lf = 0;
if( !opt.pgp2_workarounds )
pgp2mode = 0;
if( !escape_dash )
if( !escape_dash )
escape_from = 0;
write_status_begin_signing (md);
@ -194,9 +191,7 @@ copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
gcry_md_putc ( md, '\n' );
}
gcry_md_write ( md, buffer,
len_without_trailing_chars (buffer, n,
pgp2mode?
" \r\n":" \t\r\n"));
len_without_trailing_chars (buffer, n, " \t\r\n"));
}
else
gcry_md_write ( md, buffer, n );

View File

@ -24,7 +24,7 @@ dsa_usrname1="pgp5"
# we use the sub key because we do not yet have the logic to to derive
# the first encryption key from a keyblock (I guess) (Well of course
# we have this by now and the notation below will lookup the primary
# first and the search for the encryption subkey.)
# first and then search for the encryption subkey.)
dsa_usrname2="0xCB879DE9"