aboutsummaryrefslogtreecommitdiffstats
path: root/g10/mainproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r--g10/mainproc.c144
1 files changed, 106 insertions, 38 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 6ec15894d..7acf67b1e 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -86,6 +86,7 @@ struct mainproc_context
int trustletter; /* Temporary usage in list_node. */
ulong symkeys; /* Number of symmetrically encrypted session keys. */
struct pubkey_enc_list *pkenc_list; /* List of encryption packets. */
+ int seen_pkt_encrypted_aead; /* PKT_ENCRYPTED_AEAD packet seen. */
struct {
unsigned int sig_seen:1; /* Set to true if a signature packet
has been seen. */
@@ -137,6 +138,7 @@ release_list( CTX c )
c->any.data = 0;
c->any.uncompress_failed = 0;
c->last_was_session_key = 0;
+ c->seen_pkt_encrypted_aead = 0;
xfree (c->dek);
c->dek = NULL;
}
@@ -479,6 +481,7 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
x->keyid[0] = enc->keyid[0];
x->keyid[1] = enc->keyid[1];
x->pubkey_algo = enc->pubkey_algo;
+ x->result = -1;
x->data[0] = x->data[1] = NULL;
if (enc->data[0])
{
@@ -536,6 +539,9 @@ proc_encrypted (CTX c, PACKET *pkt)
int result = 0;
int early_plaintext = literals_seen;
+ if (pkt->pkttype == PKT_ENCRYPTED_AEAD)
+ c->seen_pkt_encrypted_aead = 1;
+
if (early_plaintext)
{
log_info (_("WARNING: multiple plaintexts seen\n"));
@@ -572,22 +578,21 @@ proc_encrypted (CTX c, PACKET *pkt)
{
c->dek = xmalloc_secure_clear (sizeof *c->dek);
result = get_session_key (c->ctrl, c->pkenc_list, c->dek);
- if (result == GPG_ERR_NO_SECKEY)
- {
- if (is_status_enabled ())
- {
- struct pubkey_enc_list *list;
-
- for (list = c->pkenc_list; list; list = list->next)
- {
- char buf[20];
- snprintf (buf, sizeof buf, "%08lX%08lX",
- (ulong)list->keyid[0], (ulong)list->keyid[1]);
- write_status_text (STATUS_NO_SECKEY, buf);
- }
- }
+ if (is_status_enabled ())
+ {
+ struct pubkey_enc_list *list;
+
+ for (list = c->pkenc_list; list; list = list->next)
+ if (list->result == GPG_ERR_NO_SECKEY)
+ {
+ char buf[20];
+ snprintf (buf, sizeof buf, "%08lX%08lX",
+ (ulong)list->keyid[0], (ulong)list->keyid[1]);
+ write_status_text (STATUS_NO_SECKEY, buf);
+ }
}
- else if (result)
+
+ if (result)
{
log_info (_("public key decryption failed: %s\n"),
gpg_strerror (result));
@@ -704,7 +709,6 @@ proc_encrypted (CTX c, PACKET *pkt)
}
-
if (!result)
result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
@@ -804,14 +808,31 @@ proc_encrypted (CTX c, PACKET *pkt)
}
+static int
+have_seen_pkt_encrypted_aead( CTX c )
+{
+ CTX cc;
+
+ for (cc = c; cc; cc = cc->anchor)
+ {
+ if (cc->seen_pkt_encrypted_aead)
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void
proc_plaintext( CTX c, PACKET *pkt )
{
PKT_plaintext *pt = pkt->pkt.plaintext;
int any, clearsig, rc;
kbnode_t n;
+ unsigned char *extrahash;
+ size_t extrahashlen;
- /* This is a literal data packet. Bumb a counter for later checks. */
+ /* This is a literal data packet. Bump a counter for later checks. */
literals_seen++;
if (pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8))
@@ -843,7 +864,10 @@ proc_plaintext( CTX c, PACKET *pkt )
/* The onepass signature case. */
if (n->pkt->pkt.onepass_sig->digest_algo)
{
- gcry_md_enable (c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo);
+ if (!opt.skip_verify)
+ gcry_md_enable (c->mfx.md,
+ n->pkt->pkt.onepass_sig->digest_algo);
+
any = 1;
}
}
@@ -861,7 +885,8 @@ proc_plaintext( CTX c, PACKET *pkt )
* documents. */
clearsig = (*data == 0x01);
for (data++, datalen--; datalen; datalen--, data++)
- gcry_md_enable (c->mfx.md, *data);
+ if (!opt.skip_verify)
+ gcry_md_enable (c->mfx.md, *data);
any = 1;
break; /* Stop here as one-pass signature packets are not
expected. */
@@ -869,12 +894,13 @@ proc_plaintext( CTX c, PACKET *pkt )
else if (n->pkt->pkttype == PKT_SIGNATURE)
{
/* The SIG+LITERAL case that PGP used to use. */
- gcry_md_enable ( c->mfx.md, n->pkt->pkt.signature->digest_algo );
+ if (!opt.skip_verify)
+ gcry_md_enable (c->mfx.md, n->pkt->pkt.signature->digest_algo);
any = 1;
}
}
- if (!any && !opt.skip_verify)
+ if (!any && !opt.skip_verify && !have_seen_pkt_encrypted_aead(c))
{
/* This is for the old GPG LITERAL+SIG case. It's not legal
according to 2440, so hopefully it won't come up that often.
@@ -920,12 +946,37 @@ proc_plaintext( CTX c, PACKET *pkt )
if (rc)
log_error ("handle plaintext failed: %s\n", gpg_strerror (rc));
+ /* We add a marker control packet instead of the plaintext packet.
+ * This is so that we can later detect invalid packet sequences.
+ * The apcket is further used to convey extra data from the
+ * plaintext packet to the signature verification. */
+ extrahash = xtrymalloc (6 + pt->namelen);
+ if (!extrahash)
+ {
+ /* No way to return an error. */
+ rc = gpg_error_from_syserror ();
+ log_error ("malloc failed in %s: %s\n", __func__, gpg_strerror (rc));
+ extrahashlen = 0;
+ }
+ else
+ {
+ extrahash[0] = pt->mode;
+ extrahash[1] = pt->namelen;
+ if (pt->namelen)
+ memcpy (extrahash+2, pt->name, pt->namelen);
+ extrahashlen = 2 + pt->namelen;
+ extrahash[extrahashlen++] = pt->timestamp >> 24;
+ extrahash[extrahashlen++] = pt->timestamp >> 16;
+ extrahash[extrahashlen++] = pt->timestamp >> 8;
+ extrahash[extrahashlen++] = pt->timestamp ;
+ }
+
free_packet (pkt, NULL);
c->last_was_session_key = 0;
- /* We add a marker control packet instead of the plaintext packet.
- * This is so that we can later detect invalid packet sequences. */
- n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, NULL, 0));
+ n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK,
+ extrahash, extrahashlen));
+ xfree (extrahash);
if (c->list)
add_kbnode (c->list, n);
else
@@ -995,7 +1046,8 @@ proc_compressed (CTX c, PACKET *pkt)
* found. Returns: 0 = valid signature or an error code
*/
static int
-do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
+do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen,
+ int *is_selfsig,
int *is_expkey, int *is_revkey, PKT_public_key **r_pk)
{
PKT_signature *sig;
@@ -1081,14 +1133,16 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
/* We only get here if we are checking the signature of a binary
(0x00) or text document (0x01). */
- rc = check_signature2 (c->ctrl, sig, md, NULL, is_expkey, is_revkey, r_pk);
+ rc = check_signature2 (c->ctrl, sig, md, extrahash, extrahashlen,
+ NULL, is_expkey, is_revkey, r_pk);
if (! rc)
md_good = md;
else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2)
{
PKT_public_key *pk2;
- rc = check_signature2 (c->ctrl, sig, md2, NULL, is_expkey, is_revkey,
+ rc = check_signature2 (c->ctrl, sig, md2, extrahash, extrahashlen,
+ NULL, is_expkey, is_revkey,
r_pk? &pk2 : NULL);
if (!rc)
{
@@ -1251,7 +1305,7 @@ list_node (CTX c, kbnode_t node)
if (opt.check_sigs)
{
fflush (stdout);
- rc2 = do_check_sig (c, node, &is_selfsig, NULL, NULL, NULL);
+ rc2 = do_check_sig (c, node, NULL, 0, &is_selfsig, NULL, NULL, NULL);
switch (gpg_err_code (rc2))
{
case 0: sigrc = '!'; break;
@@ -1714,7 +1768,7 @@ akl_has_wkd_method (void)
}
-/* Return the ISSUER fingerprint buffer and its lenbgth at R_LEN.
+/* Return the ISSUER fingerprint buffer and its length at R_LEN.
* Returns NULL if not available. The returned buffer is valid as
* long as SIG is not modified. */
const byte *
@@ -1724,7 +1778,7 @@ issuer_fpr_raw (PKT_signature *sig, size_t *r_len)
size_t n;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_ISSUER_FPR, &n);
- if (p && n == 21 && p[0] == 4)
+ if (p && ((n == 21 && p[0] == 4) || (n == 33 && p[0] == 5)))
{
*r_len = n - 1;
return p+1;
@@ -1787,6 +1841,8 @@ check_sig_and_print (CTX c, kbnode_t node)
char *issuer_fpr = NULL;
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
int tried_ks_by_fpr;
+ const void *extrahash = NULL;
+ size_t extrahashlen = 0;
if (opt.skip_verify)
{
@@ -1844,6 +1900,8 @@ check_sig_and_print (CTX c, kbnode_t node)
{
if (n->next)
goto ambiguous; /* We only allow one P packet. */
+ extrahash = n->pkt->pkt.gpg_control->data;
+ extrahashlen = n->pkt->pkt.gpg_control->datalen;
}
else
goto ambiguous;
@@ -1858,6 +1916,9 @@ check_sig_and_print (CTX c, kbnode_t node)
&& (n->pkt->pkt.gpg_control->control
== CTRLPKT_PLAINTEXT_MARK)))
goto ambiguous;
+ extrahash = n->pkt->pkt.gpg_control->data;
+ extrahashlen = n->pkt->pkt.gpg_control->datalen;
+
for (n_sig=0, n = n->next;
n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
n_sig++;
@@ -1888,6 +1949,8 @@ check_sig_and_print (CTX c, kbnode_t node)
&& (n->pkt->pkt.gpg_control->control
== CTRLPKT_PLAINTEXT_MARK)))
goto ambiguous;
+ extrahash = n->pkt->pkt.gpg_control->data;
+ extrahashlen = n->pkt->pkt.gpg_control->datalen;
for (n_sig=0, n = n->next;
n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
n_sig++;
@@ -1933,7 +1996,8 @@ check_sig_and_print (CTX c, kbnode_t node)
if (sig->signers_uid)
log_info (_(" issuer \"%s\"\n"), sig->signers_uid);
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
/* If the key isn't found, check for a preferred keyserver. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks)
@@ -1968,8 +2032,8 @@ check_sig_and_print (CTX c, kbnode_t node)
res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1);
glo_ctrl.in_auto_key_retrieve--;
if (!res)
- rc = do_check_sig (c, node, NULL,
- &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
free_keyserver_spec (spec);
if (!rc)
@@ -2004,7 +2068,8 @@ check_sig_and_print (CTX c, kbnode_t node)
glo_ctrl.in_auto_key_retrieve--;
free_keyserver_spec (spec);
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
}
}
}
@@ -2026,7 +2091,7 @@ check_sig_and_print (CTX c, kbnode_t node)
p = issuer_fpr_raw (sig, &n);
if (p)
{
- /* v4 packet with a SHA-1 fingerprint. */
+ /* v4 or v5 packet with a SHA-1/256 fingerprint. */
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
@@ -2034,7 +2099,8 @@ check_sig_and_print (CTX c, kbnode_t node)
tried_ks_by_fpr = 1;
glo_ctrl.in_auto_key_retrieve--;
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
}
}
@@ -2056,7 +2122,8 @@ check_sig_and_print (CTX c, kbnode_t node)
/* Fixme: If the fingerprint is embedded in the signature,
* compare it to the fingerprint of the returned key. */
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
}
/* If the above methods did't work, our next try is to use a
@@ -2074,7 +2141,8 @@ check_sig_and_print (CTX c, kbnode_t node)
res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver, 1);
glo_ctrl.in_auto_key_retrieve--;
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, extrahash, extrahashlen,
+ NULL, &is_expkey, &is_revkey, &pk);
}
if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)