mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
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 <wk@gnupg.org>
This commit is contained in:
parent
f40e9d6a52
commit
01c87d4ce2
8 changed files with 565 additions and 197 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue