aboutsummaryrefslogtreecommitdiffstats
path: root/g10/mainproc.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2019-03-14 10:20:07 +0000
committerWerner Koch <[email protected]>2019-03-14 10:26:54 +0000
commit01c87d4ce23bc9fc44ec5301c2c6bf2ce615c375 (patch)
treef19dff47ab919197f923a526e850c6954030b238 /g10/mainproc.c
parentkbx: Add support for 32 byte fingerprints. (diff)
downloadgnupg-01c87d4ce23bc9fc44ec5301c2c6bf2ce615c375.tar.gz
gnupg-01c87d4ce23bc9fc44ec5301c2c6bf2ce615c375.zip
gpg: Implement v5 keys and v5 signatures.
* g10/build-packet.c (gpg_mpi_write): New optional arg R_NWRITTEN. Allow NULL for OUT. Change all callers. (do_key): Support v5 keys. (build_sig_subpkt_from_sig): Support 32 byte fingerprints. * g10/parse-packet.c (parse_signature): First try to set the keyid from the issuer fingerprint. (parse_key): Support v5 keys. (create_gpg_control): Better make sure to always allocate the static size of the struct in case future compilers print warnings. * g10/keyid.c (hash_public_key): Add v5 support. (keyid_from_pk): Ditto. (keyid_from_fingerprint): Ditto. (fingerprint_from_pk): Ditto. * g10/keygen.c (KEYGEN_FLAG_CREATE_V5_KEY): New. (pVERSION, pSUBVERSION): New. (add_feature_v5): New. (keygen_upd_std_prefs): Call it. (do_create_from_keygrip): Add arg keygen_flags and support the v5 flag. (common_gen): Support the v5 flag. (parse_key_parameter_part): New flags v4 and v5. (parse_key_parameter_string): Add args for version and subversion. (read_parameter_file): New keywords "Key-Version" and "Subkey-Version". (quickgen_set_para): Add arg 'version'. (quick_generate_keypair, generate_keypair): Support version parms. (do_generate_keypair): Support v5 key flag. (generate_subkeypair): Ditto. (generate_card_subkeypair): Preparse for keyflags. (gen_card_key): Ditto. * g10/sig-check.c (check_signature2): Add args extrahash and extrahashlen. (check_signature_end): Ditto. (check_signature_end_simple): Ditto. Use them. * g10/mainproc.c (proc_plaintext): Put extra hash infor into the control packet. (do_check_sig): Add args extrahas and extrahashlen and pass them on. (issuer_fpr_raw): Support 32 byte fingerprint. (check_sig_and_print): get extra hash data and pass it on. -- Note that this is only basic support and requires more fine tuning/fixing. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to '')
-rw-r--r--g10/mainproc.c76
1 files changed, 60 insertions, 16 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 8c41088cc..6fa30e0d4 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -829,6 +829,8 @@ 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. Bump a counter for later checks. */
literals_seen++;
@@ -948,8 +950,33 @@ proc_plaintext( CTX c, PACKET *pkt )
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));
+ * 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 ;
+ }
+
+ n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK,
+ extrahash, extrahashlen));
+ xfree (extrahash);
if (c->list)
add_kbnode (c->list, n);
else
@@ -1019,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;
@@ -1105,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)
{
@@ -1275,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;
@@ -1738,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 *
@@ -1748,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;
@@ -1811,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)
{
@@ -1868,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;
@@ -1882,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++;
@@ -1912,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++;
@@ -1957,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)
@@ -1992,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)
@@ -2028,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);
}
}
}
@@ -2050,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++;
@@ -2058,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);
}
}
@@ -2080,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
@@ -2098,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)