1
0
Fork 0
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:
Werner Koch 2019-03-14 11:20:07 +01:00
parent f40e9d6a52
commit 01c87d4ce2
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
8 changed files with 565 additions and 197 deletions

View file

@ -37,11 +37,14 @@
static int check_signature_end (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest,
const void *extrahash, size_t extrahashlen,
int *r_expired, int *r_revoked,
PKT_public_key *ret_pk);
static int check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest);
gcry_md_hd_t digest,
const void *extrahash,
size_t extrahashlen);
/* Statistics for signature verification. */
@ -69,7 +72,7 @@ sig_check_dump_stats (void)
int
check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest)
{
return check_signature2 (ctrl, sig, digest, NULL, NULL, NULL, NULL);
return check_signature2 (ctrl, sig, digest, NULL, 0, NULL, NULL, NULL, NULL);
}
@ -95,6 +98,9 @@ check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest)
* signature data from the version number through the hashed subpacket
* data (inclusive) is hashed.")
*
* EXTRAHASH and EXTRAHASHLEN is additional data which is hashed with
* v5 signatures. They may be NULL to use the default.
*
* If R_EXPIREDATE is not NULL, R_EXPIREDATE is set to the key's
* expiry.
*
@ -112,7 +118,9 @@ check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest)
* Returns 0 on success. An error code otherwise. */
gpg_error_t
check_signature2 (ctrl_t ctrl,
PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate,
PKT_signature *sig, gcry_md_hd_t digest,
const void *extrahash, size_t extrahashlen,
u32 *r_expiredate,
int *r_expired, int *r_revoked, PKT_public_key **r_pk)
{
int rc=0;
@ -179,7 +187,8 @@ check_signature2 (ctrl_t ctrl,
if (r_expiredate)
*r_expiredate = pk->expiredate;
rc = check_signature_end (pk, sig, digest, r_expired, r_revoked, NULL);
rc = check_signature_end (pk, sig, digest, extrahash, extrahashlen,
r_expired, r_revoked, NULL);
/* Check the backsig. This is a back signature (0x19) from
* the subkey on the primary key. The idea here is that it
@ -424,6 +433,7 @@ check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig,
static int
check_signature_end (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest,
const void *extrahash, size_t extrahashlen,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk)
{
int rc = 0;
@ -432,7 +442,8 @@ check_signature_end (PKT_public_key *pk, PKT_signature *sig,
r_expired, r_revoked)))
return rc;
if ((rc = check_signature_end_simple (pk, sig, digest)))
if ((rc = check_signature_end_simple (pk, sig, digest,
extrahash, extrahashlen)))
return rc;
if (!rc && ret_pk)
@ -447,7 +458,8 @@ check_signature_end (PKT_public_key *pk, PKT_signature *sig,
* expiration, revocation, etc. */
static int
check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest)
gcry_md_hd_t digest,
const void *extrahash, size_t extrahashlen)
{
gcry_mpi_t result = NULL;
int rc = 0;
@ -539,8 +551,13 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
/* - One octet content format
* - File name (one octet length followed by the name)
* - Four octet timestamp */
memset (buf, 0, 6);
gcry_md_write (digest, buf, 6);
if (extrahash && extrahashlen)
gcry_md_write (digest, extrahash, extrahashlen);
else /* Detached signature. */
{
memset (buf, 0, 6);
gcry_md_write (digest, buf, 6);
}
}
/* Add some magic per Section 5.2.4 of RFC 4880. */
i = 0;
@ -790,7 +807,7 @@ check_backsig (PKT_public_key *main_pk,PKT_public_key *sub_pk,
{
hash_public_key(md,main_pk);
hash_public_key(md,sub_pk);
rc = check_signature_end (sub_pk, backsig, md, NULL, NULL, NULL);
rc = check_signature_end (sub_pk, backsig, md, NULL, 0, NULL, NULL, NULL);
cache_sig_result(backsig,rc);
gcry_md_close(md);
}
@ -977,28 +994,28 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
{
log_assert (packet->pkttype == PKT_PUBLIC_KEY);
hash_public_key (md, packet->pkt.public_key);
rc = check_signature_end_simple (signer, sig, md);
rc = check_signature_end_simple (signer, sig, md, NULL, 0);
}
else if (IS_BACK_SIG (sig))
{
log_assert (packet->pkttype == PKT_PUBLIC_KEY);
hash_public_key (md, packet->pkt.public_key);
hash_public_key (md, signer);
rc = check_signature_end_simple (signer, sig, md);
rc = check_signature_end_simple (signer, sig, md, NULL, 0);
}
else if (IS_SUBKEY_SIG (sig) || IS_SUBKEY_REV (sig))
{
log_assert (packet->pkttype == PKT_PUBLIC_SUBKEY);
hash_public_key (md, pripk);
hash_public_key (md, packet->pkt.public_key);
rc = check_signature_end_simple (signer, sig, md);
rc = check_signature_end_simple (signer, sig, md, NULL, 0);
}
else if (IS_UID_SIG (sig) || IS_UID_REV (sig))
{
log_assert (packet->pkttype == PKT_USER_ID);
hash_public_key (md, pripk);
hash_uid_packet (packet->pkt.user_id, md, sig);
rc = check_signature_end_simple (signer, sig, md);
rc = check_signature_end_simple (signer, sig, md, NULL, 0);
}
else
{