gpg: Re-indent sig-check.c and use signature class macros.

* g10/keydb.h (IS_BACK_SIG): New.
* g10/sig-check.c: Re-indent and use macros.
--

This makes the code easier to understand.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2018-04-06 10:18:53 +02:00
parent 80b775bdbb
commit 5ba74a134d
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 375 additions and 390 deletions

View File

@ -33,6 +33,7 @@
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
#define IS_SUBKEY_SIG(s) ((s)->sig_class == 0x18)
#define IS_BACK_SIG(s) ((s)->sig_class == 0x19)
#define IS_KEY_REV(s) ((s)->sig_class == 0x20)
#define IS_UID_REV(s) ((s)->sig_class == 0x30)
#define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28)

View File

@ -115,174 +115,177 @@ check_signature2 (ctrl_t ctrl,
PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate,
int *r_expired, int *r_revoked, PKT_public_key **r_pk)
{
int rc=0;
PKT_public_key *pk;
int rc=0;
PKT_public_key *pk;
if (r_expiredate)
*r_expiredate = 0;
if (r_expired)
*r_expired = 0;
if (r_revoked)
*r_revoked = 0;
if (r_pk)
*r_pk = NULL;
if (r_expiredate)
*r_expiredate = 0;
if (r_expired)
*r_expired = 0;
if (r_revoked)
*r_revoked = 0;
if (r_pk)
*r_pk = NULL;
pk = xtrycalloc (1, sizeof *pk);
if (!pk)
return gpg_error_from_syserror ();
pk = xtrycalloc (1, sizeof *pk);
if (!pk)
return gpg_error_from_syserror ();
if ( (rc=openpgp_md_test_algo(sig->digest_algo)) )
; /* We don't have this digest. */
else if (! gnupg_digest_is_allowed (opt.compliance, 0, sig->digest_algo))
{
/* Compliance failure. */
log_info (_("digest algorithm '%s' may not be used in %s mode\n"),
gcry_md_algo_name (sig->digest_algo),
gnupg_compliance_option_string (opt.compliance));
rc = gpg_error (GPG_ERR_DIGEST_ALGO);
}
else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo)))
; /* We don't have this pubkey algo. */
else if (!gcry_md_is_enabled (digest,sig->digest_algo))
{
/* Sanity check that the md has a context for the hash that the
sig is expecting. This can happen if a onepass sig header does
not match the actual sig, and also if the clearsign "Hash:"
header is missing or does not match the actual sig. */
if ((rc=openpgp_md_test_algo(sig->digest_algo)))
{
/* We don't have this digest. */
}
else if (!gnupg_digest_is_allowed (opt.compliance, 0, sig->digest_algo))
{
/* Compliance failure. */
log_info (_("digest algorithm '%s' may not be used in %s mode\n"),
gcry_md_algo_name (sig->digest_algo),
gnupg_compliance_option_string (opt.compliance));
rc = gpg_error (GPG_ERR_DIGEST_ALGO);
}
else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo)))
{
/* We don't have this pubkey algo. */
}
else if (!gcry_md_is_enabled (digest,sig->digest_algo))
{
/* Sanity check that the md has a context for the hash that the
* sig is expecting. This can happen if a onepass sig header
* does not match the actual sig, and also if the clearsign
* "Hash:" header is missing or does not match the actual sig. */
log_info(_("WARNING: signature digest conflict in message\n"));
rc = gpg_error (GPG_ERR_GENERAL);
}
else if (get_pubkey (ctrl, pk, sig->keyid))
rc = gpg_error (GPG_ERR_NO_PUBKEY);
else if (!gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
pk->pubkey_algo, pk->pkey,
nbits_from_pk (pk),
NULL))
{
/* Compliance failure. */
log_error (_("key %s may not be used for signing in %s mode\n"),
keystr_from_pk (pk),
gnupg_compliance_option_string (opt.compliance));
rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
}
else if (!pk->flags.valid)
{
/* You cannot have a good sig from an invalid key. */
rc = gpg_error (GPG_ERR_BAD_PUBKEY);
}
else
{
if (r_expiredate)
*r_expiredate = pk->expiredate;
log_info(_("WARNING: signature digest conflict in message\n"));
rc = gpg_error (GPG_ERR_GENERAL);
}
else if( get_pubkey (ctrl, pk, sig->keyid ) )
rc = gpg_error (GPG_ERR_NO_PUBKEY);
else if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
pk->pubkey_algo, pk->pkey,
nbits_from_pk (pk),
NULL))
{
/* Compliance failure. */
log_error (_("key %s may not be used for signing in %s mode\n"),
keystr_from_pk (pk),
gnupg_compliance_option_string (opt.compliance));
rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
}
else if(!pk->flags.valid)
{
/* You cannot have a good sig from an invalid key. */
rc = gpg_error (GPG_ERR_BAD_PUBKEY);
}
else
{
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, 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
* should not be possible for someone to "steal" subkeys and
* claim them as their own. The attacker couldn't actually
* use the subkey, but they could try and claim ownership of
* any signatures issued by it. */
if (!rc && !pk->flags.primary && pk->flags.backsig < 2)
{
if (!pk->flags.backsig)
{
log_info (_("WARNING: signing subkey %s is not"
" cross-certified\n"),keystr_from_pk(pk));
log_info (_("please see %s for more information\n"),
"https://gnupg.org/faq/subkey-cross-certify.html");
/* The default option --require-cross-certification
* makes this warning an error. */
if (opt.flags.require_cross_cert)
rc = gpg_error (GPG_ERR_GENERAL);
}
else if(pk->flags.backsig == 1)
{
log_info (_("WARNING: signing subkey %s has an invalid"
" cross-certification\n"), keystr_from_pk(pk));
rc = gpg_error (GPG_ERR_GENERAL);
}
}
/* Check the backsig. This is a 0x19 signature from the
subkey on the primary key. The idea here is that it should
not be possible for someone to "steal" subkeys and claim
them as their own. The attacker couldn't actually use the
subkey, but they could try and claim ownership of any
signatures issued by it. */
if (!rc && !pk->flags.primary && pk->flags.backsig < 2)
{
if (!pk->flags.backsig)
{
log_info(_("WARNING: signing subkey %s is not"
" cross-certified\n"),keystr_from_pk(pk));
log_info(_("please see %s for more information\n"),
"https://gnupg.org/faq/subkey-cross-certify.html");
/* --require-cross-certification makes this warning an
error. TODO: change the default to require this
after more keys have backsigs. */
if(opt.flags.require_cross_cert)
rc = gpg_error (GPG_ERR_GENERAL);
}
else if(pk->flags.backsig == 1)
{
log_info(_("WARNING: signing subkey %s has an invalid"
" cross-certification\n"),keystr_from_pk(pk));
rc = gpg_error (GPG_ERR_GENERAL);
}
}
}
if( !rc && sig->sig_class < 2 && is_status_enabled() ) {
/* This signature id works best with DLP algorithms because
* they use a random parameter for every signature. Instead of
* this sig-id we could have also used the hash of the document
* and the timestamp, but the drawback of this is, that it is
* not possible to sign more than one identical document within
* one second. Some remote batch processing applications might
* like this feature here.
*
* Note that before 2.0.10, we used RIPE-MD160 for the hash
* and accidentally didn't include the timestamp and algorithm
* information in the hash. Given that this feature is not
* commonly used and that a replay attacks detection should
* not solely be based on this feature (because it does not
* work with RSA), we take the freedom and switch to SHA-1
* with 2.0.10 to take advantage of hardware supported SHA-1
* implementations. We also include the missing information
* in the hash. Note also the SIG_ID as computed by gpg 1.x
* and gpg 2.x didn't matched either because 2.x used to print
* MPIs not in PGP format. */
u32 a = sig->timestamp;
int nsig = pubkey_get_nsig( sig->pubkey_algo );
unsigned char *p, *buffer;
size_t n, nbytes;
int i;
char hashbuf[20];
nbytes = 6;
for (i=0; i < nsig; i++ )
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n, sig->data[i]))
BUG();
nbytes += n;
}
/* Make buffer large enough to be later used as output buffer. */
if (nbytes < 100)
nbytes = 100;
nbytes += 10; /* Safety margin. */
/* Fill and hash buffer. */
buffer = p = xmalloc (nbytes);
*p++ = sig->pubkey_algo;
*p++ = sig->digest_algo;
*p++ = (a >> 24) & 0xff;
*p++ = (a >> 16) & 0xff;
*p++ = (a >> 8) & 0xff;
*p++ = a & 0xff;
nbytes -= 6;
for (i=0; i < nsig; i++ )
{
if (gcry_mpi_print (GCRYMPI_FMT_PGP, p, nbytes, &n, sig->data[i]))
BUG();
p += n;
nbytes -= n;
}
gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, buffer, p-buffer);
p = make_radix64_string (hashbuf, 20);
sprintf (buffer, "%s %s %lu",
p, strtimestamp (sig->timestamp), (ulong)sig->timestamp);
xfree (p);
write_status_text (STATUS_SIG_ID, buffer);
xfree (buffer);
}
if (r_pk)
*r_pk = pk;
else
{
release_public_key_parts (pk);
xfree (pk);
}
if (!rc && sig->sig_class < 2 && is_status_enabled ())
{
/* This signature id works best with DLP algorithms because
* they use a random parameter for every signature. Instead of
* this sig-id we could have also used the hash of the document
* and the timestamp, but the drawback of this is, that it is
* not possible to sign more than one identical document within
* one second. Some remote batch processing applications might
* like this feature here.
*
* Note that before 2.0.10, we used RIPE-MD160 for the hash
* and accidentally didn't include the timestamp and algorithm
* information in the hash. Given that this feature is not
* commonly used and that a replay attacks detection should
* not solely be based on this feature (because it does not
* work with RSA), we take the freedom and switch to SHA-1
* with 2.0.10 to take advantage of hardware supported SHA-1
* implementations. We also include the missing information
* in the hash. Note also the SIG_ID as computed by gpg 1.x
* and gpg 2.x didn't matched either because 2.x used to print
* MPIs not in PGP format. */
u32 a = sig->timestamp;
int nsig = pubkey_get_nsig (sig->pubkey_algo);
unsigned char *p, *buffer;
size_t n, nbytes;
int i;
char hashbuf[20];
return rc;
nbytes = 6;
for (i=0; i < nsig; i++ )
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n, sig->data[i]))
BUG();
nbytes += n;
}
/* Make buffer large enough to be later used as output buffer. */
if (nbytes < 100)
nbytes = 100;
nbytes += 10; /* Safety margin. */
/* Fill and hash buffer. */
buffer = p = xmalloc (nbytes);
*p++ = sig->pubkey_algo;
*p++ = sig->digest_algo;
*p++ = (a >> 24) & 0xff;
*p++ = (a >> 16) & 0xff;
*p++ = (a >> 8) & 0xff;
*p++ = a & 0xff;
nbytes -= 6;
for (i=0; i < nsig; i++ )
{
if (gcry_mpi_print (GCRYMPI_FMT_PGP, p, nbytes, &n, sig->data[i]))
BUG();
p += n;
nbytes -= n;
}
gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, buffer, p-buffer);
p = make_radix64_string (hashbuf, 20);
sprintf (buffer, "%s %s %lu",
p, strtimestamp (sig->timestamp), (ulong)sig->timestamp);
xfree (p);
write_status_text (STATUS_SIG_ID, buffer);
xfree (buffer);
}
if (r_pk)
*r_pk = pk;
else
{
release_public_key_parts (pk);
xfree (pk);
}
return rc;
}
@ -307,87 +310,86 @@ static int
check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig,
int *r_expired, int *r_revoked)
{
u32 cur_time;
u32 cur_time;
if(r_expired)
*r_expired = 0;
if(r_revoked)
*r_revoked = 0;
if (r_expired)
*r_expired = 0;
if (r_revoked)
*r_revoked = 0;
if( pk->timestamp > sig->timestamp )
{
ulong d = pk->timestamp - sig->timestamp;
if ( d < 86400 )
{
log_info
(ngettext
("public key %s is %lu second newer than the signature\n",
"public key %s is %lu seconds newer than the signature\n",
d), keystr_from_pk (pk), d);
}
else
{
d /= 86400;
log_info
(ngettext
("public key %s is %lu day newer than the signature\n",
"public key %s is %lu days newer than the signature\n",
d), keystr_from_pk (pk), d);
}
if (!opt.ignore_time_conflict)
return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature. */
}
cur_time = make_timestamp();
if( pk->timestamp > cur_time )
{
ulong d = pk->timestamp - cur_time;
if (d < 86400)
{
log_info (ngettext("key %s was created %lu second"
" in the future (time warp or clock problem)\n",
"key %s was created %lu seconds"
" in the future (time warp or clock problem)\n",
d), keystr_from_pk (pk), d);
}
else
{
d /= 86400;
log_info (ngettext("key %s was created %lu day"
" in the future (time warp or clock problem)\n",
"key %s was created %lu days"
" in the future (time warp or clock problem)\n",
d), keystr_from_pk (pk), d);
}
if (!opt.ignore_time_conflict)
return GPG_ERR_TIME_CONFLICT;
}
/* Check whether the key has expired. We check the has_expired
flag which is set after a full evaluation of the key (getkey.c)
as well as a simple compare to the current time in case the
merge has for whatever reasons not been done. */
if( pk->has_expired || (pk->expiredate && pk->expiredate < cur_time)) {
char buf[11];
if (opt.verbose)
log_info(_("Note: signature key %s expired %s\n"),
keystr_from_pk(pk), asctimestamp( pk->expiredate ) );
sprintf(buf,"%lu",(ulong)pk->expiredate);
write_status_text(STATUS_KEYEXPIRED,buf);
if(r_expired)
*r_expired = 1;
if (pk->timestamp > sig->timestamp )
{
ulong d = pk->timestamp - sig->timestamp;
if ( d < 86400 )
{
log_info (ngettext
("public key %s is %lu second newer than the signature\n",
"public key %s is %lu seconds newer than the signature\n",
d), keystr_from_pk (pk), d);
}
else
{
d /= 86400;
log_info (ngettext
("public key %s is %lu day newer than the signature\n",
"public key %s is %lu days newer than the signature\n",
d), keystr_from_pk (pk), d);
}
if (!opt.ignore_time_conflict)
return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature. */
}
if (pk->flags.revoked)
{
if (opt.verbose)
log_info (_("Note: signature key %s has been revoked\n"),
keystr_from_pk(pk));
if (r_revoked)
*r_revoked=1;
}
cur_time = make_timestamp ();
if (pk->timestamp > cur_time)
{
ulong d = pk->timestamp - cur_time;
if (d < 86400)
{
log_info (ngettext("key %s was created %lu second"
" in the future (time warp or clock problem)\n",
"key %s was created %lu seconds"
" in the future (time warp or clock problem)\n",
d), keystr_from_pk (pk), d);
}
else
{
d /= 86400;
log_info (ngettext("key %s was created %lu day"
" in the future (time warp or clock problem)\n",
"key %s was created %lu days"
" in the future (time warp or clock problem)\n",
d), keystr_from_pk (pk), d);
}
if (!opt.ignore_time_conflict)
return GPG_ERR_TIME_CONFLICT;
}
return 0;
/* Check whether the key has expired. We check the has_expired
* flag which is set after a full evaluation of the key (getkey.c)
* as well as a simple compare to the current time in case the
* merge has for whatever reasons not been done. */
if (pk->has_expired || (pk->expiredate && pk->expiredate < cur_time))
{
char buf[11];
if (opt.verbose)
log_info (_("Note: signature key %s expired %s\n"),
keystr_from_pk(pk), asctimestamp( pk->expiredate ) );
snprintf (buf, sizeof buf, "%lu",(ulong)pk->expiredate);
write_status_text (STATUS_KEYEXPIRED, buf);
if (r_expired)
*r_expired = 1;
}
if (pk->flags.revoked)
{
if (opt.verbose)
log_info (_("Note: signature key %s has been revoked\n"),
keystr_from_pk(pk));
if (r_revoked)
*r_revoked=1;
}
return 0;
}
@ -425,150 +427,165 @@ check_signature_end (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk)
{
int rc = 0;
if ((rc = check_signature_metadata_validity (pk, sig,
r_expired, r_revoked)))
return rc;
if ((rc = check_signature_end_simple (pk, sig, digest)))
return rc;
if(!rc && ret_pk)
copy_public_key(ret_pk,pk);
int rc = 0;
if ((rc = check_signature_metadata_validity (pk, sig,
r_expired, r_revoked)))
return rc;
if ((rc = check_signature_end_simple (pk, sig, digest)))
return rc;
if (!rc && ret_pk)
copy_public_key(ret_pk,pk);
return rc;
}
/* This function is similar to check_signature_end, but it only checks
whether the signature was generated by PK. It does not check
expiration, revocation, etc. */
* whether the signature was generated by PK. It does not check
* expiration, revocation, etc. */
static int
check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest)
{
gcry_mpi_t result = NULL;
int rc = 0;
const struct weakhash *weak;
gcry_mpi_t result = NULL;
int rc = 0;
const struct weakhash *weak;
if (!opt.flags.allow_weak_digest_algos)
if (!opt.flags.allow_weak_digest_algos)
{
for (weak = opt.weak_digests; weak; weak = weak->next)
if (sig->digest_algo == weak->algo)
{
print_digest_rejected_note(sig->digest_algo);
return GPG_ERR_DIGEST_ALGO;
}
/* Make sure the digest algo is enabled (in case of a detached
signature). */
gcry_md_enable (digest, sig->digest_algo);
/* Complete the digest. */
if( sig->version >= 4 )
gcry_md_putc( digest, sig->version );
gcry_md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
gcry_md_putc( digest, (a >> 24) & 0xff );
gcry_md_putc( digest, (a >> 16) & 0xff );
gcry_md_putc( digest, (a >> 8) & 0xff );
gcry_md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
gcry_md_putc( digest, sig->pubkey_algo );
gcry_md_putc( digest, sig->digest_algo );
if( sig->hashed ) {
n = sig->hashed->len;
gcry_md_putc (digest, (n >> 8) );
gcry_md_putc (digest, n );
gcry_md_write (digest, sig->hashed->data, n);
n += 6;
/* Make sure the digest algo is enabled (in case of a detached
* signature). */
gcry_md_enable (digest, sig->digest_algo);
/* Complete the digest. */
if (sig->version >= 4)
gcry_md_putc (digest, sig->version);
gcry_md_putc( digest, sig->sig_class );
if (sig->version < 4)
{
u32 a = sig->timestamp;
gcry_md_putc (digest, ((a >> 24) & 0xff));
gcry_md_putc (digest, ((a >> 16) & 0xff));
gcry_md_putc (digest, ((a >> 8) & 0xff));
gcry_md_putc (digest, ( a & 0xff));
}
else
{
byte buf[6];
size_t n;
gcry_md_putc (digest, sig->pubkey_algo);
gcry_md_putc (digest, sig->digest_algo);
if (sig->hashed)
{
n = sig->hashed->len;
gcry_md_putc (digest, (n >> 8) );
gcry_md_putc (digest, n );
gcry_md_write (digest, sig->hashed->data, n);
n += 6;
}
else {
else
{
/* Two octets for the (empty) length of the hashed
section. */
* section. */
gcry_md_putc (digest, 0);
gcry_md_putc (digest, 0);
n = 6;
}
/* add some magic per Section 5.2.4 of RFC 4880. */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
gcry_md_write( digest, buf, 6 );
/* Add some magic per Section 5.2.4 of RFC 4880. */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
gcry_md_write( digest, buf, 6 );
}
gcry_md_final( digest );
gcry_md_final( digest );
/* Convert the digest to an MPI. */
result = encode_md_value (pk, digest, sig->digest_algo );
if (!result)
return GPG_ERR_GENERAL;
/* Convert the digest to an MPI. */
result = encode_md_value (pk, digest, sig->digest_algo );
if (!result)
return GPG_ERR_GENERAL;
/* Verify the signature. */
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey );
gcry_mpi_release (result);
/* Verify the signature. */
rc = pk_verify (pk->pubkey_algo, result, sig->data, pk->pkey);
gcry_mpi_release (result);
if( !rc && sig->flags.unknown_critical )
{
log_info(_("assuming bad signature from key %s"
" due to an unknown critical bit\n"),keystr_from_pk(pk));
rc = GPG_ERR_BAD_SIGNATURE;
}
if (!rc && sig->flags.unknown_critical)
{
log_info(_("assuming bad signature from key %s"
" due to an unknown critical bit\n"),keystr_from_pk(pk));
rc = GPG_ERR_BAD_SIGNATURE;
}
return rc;
return rc;
}
/* Add a uid node to a hash context. See section 5.2.4, paragraph 4
of RFC 4880. */
* of RFC 4880. */
static void
hash_uid_packet (PKT_user_id *uid, gcry_md_hd_t md, PKT_signature *sig )
{
if( uid->attrib_data ) {
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xd1; /* packet of type 17 */
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;
gcry_md_write( md, buf, 5 );
if (uid->attrib_data)
{
if (sig->version >=4)
{
byte buf[5];
buf[0] = 0xd1; /* packet of type 17 */
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;
gcry_md_write( md, buf, 5 );
}
gcry_md_write( md, uid->attrib_data, uid->attrib_len );
gcry_md_write( md, uid->attrib_data, uid->attrib_len );
}
else {
if( sig->version >=4 ) {
byte buf[5];
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 );
else
{
if (sig->version >=4)
{
byte buf[5];
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 );
}
gcry_md_write( md, uid->name, uid->len );
gcry_md_write( md, uid->name, uid->len );
}
}
static void
cache_sig_result ( PKT_signature *sig, int result )
{
if ( !result ) {
sig->flags.checked = 1;
sig->flags.valid = 1;
if (!result)
{
sig->flags.checked = 1;
sig->flags.valid = 1;
}
else if ( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) {
sig->flags.checked = 1;
sig->flags.valid = 0;
else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE)
{
sig->flags.checked = 1;
sig->flags.valid = 0;
}
else {
sig->flags.checked = 0;
sig->flags.valid = 0;
else
{
sig->flags.checked = 0;
sig->flags.valid = 0;
}
}
@ -686,14 +703,14 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
}
/* Check that the backsig BACKSIG from the subkey SUB_PK to its
primary key MAIN_PK is valid.
Backsigs (0x19) have the same format as binding sigs (0x18), but
this function is simpler than check_key_signature in a few ways.
For example, there is no support for expiring backsigs since it is
questionable what such a thing actually means. Note also that the
sig cache check here, unlike other sig caches in GnuPG, is not
persistent. */
* primary key MAIN_PK is valid.
*
* Backsigs (0x19) have the same format as binding sigs (0x18), but
* this function is simpler than check_key_signature in a few ways.
* For example, there is no support for expiring backsigs since it is
* questionable what such a thing actually means. Note also that the
* sig cache check here, unlike other sig caches in GnuPG, is not
* persistent. */
int
check_backsig (PKT_public_key *main_pk,PKT_public_key *sub_pk,
PKT_signature *backsig)
@ -789,32 +806,18 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
/* A signature's class indicates the type of packet that it
signs. */
if (/* Primary key binding (made by a subkey). */
sig->sig_class == 0x19
/* Direct key signature. */
|| sig->sig_class == 0x1f
/* Primary key revocation. */
|| sig->sig_class == 0x20)
if (IS_BACK_SIG (sig) || IS_KEY_SIG (sig) || IS_KEY_REV (sig))
{
/* Key revocations can only be over primary keys. */
if (packet->pkttype != PKT_PUBLIC_KEY)
return gpg_error (GPG_ERR_SIG_CLASS);
}
else if (/* Subkey binding. */
sig->sig_class == 0x18
/* Subkey revocation. */
|| sig->sig_class == 0x28)
else if (IS_SUBKEY_SIG (sig) || IS_SUBKEY_REV (sig))
{
if (packet->pkttype != PKT_PUBLIC_SUBKEY)
return gpg_error (GPG_ERR_SIG_CLASS);
}
else if (/* Certification. */
sig->sig_class == 0x10
|| sig->sig_class == 0x11
|| sig->sig_class == 0x12
|| sig->sig_class == 0x13
/* Certification revocation. */
|| sig->sig_class == 0x30)
else if (IS_UID_SIG (sig) || IS_UID_REV (sig))
{
if (packet->pkttype != PKT_USER_ID)
return gpg_error (GPG_ERR_SIG_CLASS);
@ -849,7 +852,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
else
{
/* See if one of the subkeys was the signer (although this
is extremely unlikely). */
* is extremely unlikely). */
kbnode_t ctx = NULL;
kbnode_t n;
@ -909,40 +912,27 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
/* Hash the relevant data. */
if (/* Direct key signature. */
sig->sig_class == 0x1f
/* Primary key revocation. */
|| sig->sig_class == 0x20)
if (IS_KEY_SIG (sig) || IS_KEY_REV (sig))
{
log_assert (packet->pkttype == PKT_PUBLIC_KEY);
hash_public_key (md, packet->pkt.public_key);
rc = check_signature_end_simple (signer, sig, md);
}
else if (/* Primary key binding (made by a subkey). */
sig->sig_class == 0x19)
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);
}
else if (/* Subkey binding. */
sig->sig_class == 0x18
/* Subkey revocation. */
|| sig->sig_class == 0x28)
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);
}
else if (/* Certification. */
sig->sig_class == 0x10
|| sig->sig_class == 0x11
|| sig->sig_class == 0x12
|| sig->sig_class == 0x13
/* Certification revocation. */
|| sig->sig_class == 0x30)
else if (IS_UID_SIG (sig) || IS_UID_REV (sig))
{
log_assert (packet->pkttype == PKT_USER_ID);
hash_public_key (md, pripk);
@ -1073,7 +1063,7 @@ check_key_signature2 (ctrl_t ctrl,
if (rc)
return rc;
if (sig->sig_class == 0x20) /* key revocation */
if (IS_KEY_REV (sig))
{
u32 keyid[2];
keyid_from_pk( pk, keyid );
@ -1091,8 +1081,7 @@ check_key_signature2 (ctrl_t ctrl,
is_selfsig, ret_pk);
}
}
else if (sig->sig_class == 0x28 /* subkey revocation */
|| sig->sig_class == 0x18) /* key binding */
else if (IS_SUBKEY_REV (sig) || IS_SUBKEY_SIG (sig))
{
kbnode_t snode = find_prev_kbnode (root, node, PKT_PUBLIC_SUBKEY);
@ -1102,9 +1091,10 @@ check_key_signature2 (ctrl_t ctrl,
r_expired, NULL);
if (! rc)
{
/* 0x28 must be a self-sig, but 0x18 needn't be. */
/* A subkey revocation (0x28) must be a self-sig, but a
* subkey signature (0x18) needn't be. */
rc = check_signature_over_key_or_uid (ctrl,
sig->sig_class == 0x18
IS_SUBKEY_SIG (sig)
? NULL : pk,
sig, root, snode->pkt,
is_selfsig, ret_pk);
@ -1114,7 +1104,7 @@ check_key_signature2 (ctrl_t ctrl,
{
if (opt.verbose)
{
if (sig->sig_class == 0x28)
if (IS_SUBKEY_REV (sig))
log_info (_("key %s: no subkey for subkey"
" revocation signature\n"), keystr_from_pk(pk));
else if (sig->sig_class == 0x18)
@ -1124,7 +1114,7 @@ check_key_signature2 (ctrl_t ctrl,
rc = GPG_ERR_SIG_CLASS;
}
}
else if (sig->sig_class == 0x1f) /* direct key signature */
else if (IS_KEY_SIG (sig)) /* direct key signature */
{
rc = check_signature_metadata_validity (pk, sig,
r_expired, NULL);
@ -1132,13 +1122,7 @@ check_key_signature2 (ctrl_t ctrl,
rc = check_signature_over_key_or_uid (ctrl, pk, sig, root, root->pkt,
is_selfsig, ret_pk);
}
else if (/* Certification. */
sig->sig_class == 0x10
|| sig->sig_class == 0x11
|| sig->sig_class == 0x12
|| sig->sig_class == 0x13
/* Certification revocation. */
|| sig->sig_class == 0x30)
else if (IS_UID_SIG (sig) || IS_UID_REV (sig))
{
kbnode_t unode = find_prev_kbnode (root, node, PKT_USER_ID);