aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/getkey.c21
-rw-r--r--g10/keydb.h6
-rw-r--r--g10/misc.c8
-rw-r--r--g10/packet.h4
-rw-r--r--g10/pkclist.c36
-rw-r--r--g10/sig-check.c3
6 files changed, 54 insertions, 24 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index e5f3a6d08..7822fd109 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1794,7 +1794,8 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
*
* This function returns 0 on success. Otherwise, an error code is
* returned. In particular, GPG_ERR_NO_PUBKEY is returned if the key
- * is not found.
+ * is not found. If R_KEYBLOCK is not NULL and a key was found the
+ * keyblock is stored there; otherwiese NULL is stored there.
*
* The self-signed data has already been merged into the public key
* using merge_selfsigs. The caller must release the content of PK by
@@ -1802,13 +1803,17 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
* free_public_key).
*/
gpg_error_t
-get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
+get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname,
+ kbnode_t *r_keyblock)
{
gpg_error_t err;
kbnode_t keyblock;
kbnode_t found_key;
unsigned int infoflags;
+ if (r_keyblock)
+ *r_keyblock = NULL;
+
err = read_key_from_file_or_buffer (ctrl, fname, NULL, 0, &keyblock);
if (!err)
{
@@ -1823,7 +1828,10 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
}
- release_kbnode (keyblock);
+ if (!err && r_keyblock)
+ *r_keyblock = keyblock;
+ else
+ release_kbnode (keyblock);
return err;
}
@@ -1885,12 +1893,12 @@ get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
* returned public key may be a subkey rather than the primary key.
* Note: The self-signed data has already been merged into the public
* key using merge_selfsigs. Free *PK by calling
- * release_public_key_parts (or, if PK was allocated using xfree, you
+ * release_public_key_parts (or, if PK was allocated using xmalloc, you
* can use free_public_key, which calls release_public_key_parts(PK)
* and then xfree(PK)).
*
* If PK->REQ_USAGE is set, it is used to filter the search results.
- * (Thus, if PK is not NULL, PK->REQ_USAGE must be valid!!!) See the
+ * Thus, if PK is not NULL, PK->REQ_USAGE must be valid! See the
* documentation for finish_lookup to understand exactly how this is
* used.
*
@@ -2491,7 +2499,8 @@ merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock)
}
-static int
+/* This function parses the key flags and returns PUBKEY_USAGE_ flags. */
+unsigned int
parse_key_usage (PKT_signature * sig)
{
int key_usage = 0;
diff --git a/g10/keydb.h b/g10/keydb.h
index 4be889e07..074027690 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -377,7 +377,8 @@ gpg_error_t get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
/* Get a public key directly from file FNAME. */
gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
- PKT_public_key *pk, const char *fname);
+ PKT_public_key *pk, const char *fname,
+ kbnode_t *r_keyblock);
/* Get a public key from a buffer. */
gpg_error_t get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
@@ -453,6 +454,9 @@ void setup_main_keyids (kbnode_t keyblock);
data structures. */
void merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock);
+/* This function parses the key flags and returns PUBKEY_USAGE_ flags. */
+unsigned int parse_key_usage (PKT_signature *sig);
+
char *get_user_id_string_native (ctrl_t ctrl, u32 *keyid);
char *get_long_user_id_string (ctrl_t ctrl, u32 *keyid);
char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid);
diff --git a/g10/misc.c b/g10/misc.c
index 23a627a66..768e02da3 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -782,21 +782,21 @@ openpgp_pk_algo_usage ( int algo )
switch ( algo ) {
case PUBKEY_ALGO_RSA:
use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
- | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
+ | PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC | PUBKEY_USAGE_AUTH);
break;
case PUBKEY_ALGO_RSA_E:
case PUBKEY_ALGO_ECDH:
- use = PUBKEY_USAGE_ENC;
+ use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_RSA_S:
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
break;
case PUBKEY_ALGO_ELGAMAL:
if (RFC2440)
- use = PUBKEY_USAGE_ENC;
+ use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_ELGAMAL_E:
- use = PUBKEY_USAGE_ENC;
+ use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_DSA:
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
diff --git a/g10/packet.h b/g10/packet.h
index e5bedac21..409d7d419 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -290,7 +290,7 @@ typedef struct
/* The length of ATTRIB_DATA. */
unsigned long attrib_len;
byte *namehash;
- int help_key_usage;
+ u16 help_key_usage;
u32 help_key_expire;
int help_full_count;
int help_marginal_count;
@@ -388,7 +388,7 @@ typedef struct
byte selfsigversion; /* highest version of all of the self-sigs */
/* The public key algorithm. (Serialized.) */
byte pubkey_algo;
- byte pubkey_usage; /* for now only used to pass it to getkey() */
+ u16 pubkey_usage; /* carries the usage info. */
byte req_usage; /* hack to pass a request to getkey() */
u32 has_expired; /* set to the expiration date if expired */
/* keyid of the primary key. Never access this value directly.
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 54326822d..3fd7995c3 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -821,7 +821,8 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
{
int rc;
PKT_public_key *pk;
- KBNODE keyblock = NULL;
+ kbnode_t keyblock = NULL;
+ kbnode_t node;
if (!name || !*name)
return gpg_error (GPG_ERR_INV_USER_ID);
@@ -832,7 +833,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
pk->req_usage = use;
if (from_file)
- rc = get_pubkey_fromfile (ctrl, pk, name);
+ rc = get_pubkey_fromfile (ctrl, pk, name, &keyblock);
else
rc = get_best_pubkey_byname (ctrl, GET_PUBKEY_NORMAL,
NULL, pk, name, &keyblock, 0);
@@ -871,10 +872,10 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
int trustlevel;
trustlevel = get_validity (ctrl, keyblock, pk, pk->user_id, NULL, 1);
- release_kbnode (keyblock);
if ( (trustlevel & TRUST_FLAG_DISABLED) )
{
/* Key has been disabled. */
+ release_kbnode (keyblock);
send_status_inv_recp (13, name);
log_info (_("%s: skipped: public key is disabled\n"), name);
free_public_key (pk);
@@ -884,6 +885,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
if ( !do_we_trust_pre (ctrl, pk, trustlevel) )
{
/* We don't trust this key. */
+ release_kbnode (keyblock);
send_status_inv_recp (10, name);
free_public_key (pk);
return GPG_ERR_UNUSABLE_PUBKEY;
@@ -902,19 +904,33 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
{
pk_list_t r;
- r = xtrymalloc (sizeof *r);
- if (!r)
- {
- rc = gpg_error_from_syserror ();
- free_public_key (pk);
- return rc;
- }
+ r = xmalloc (sizeof *r);
r->pk = pk;
r->next = *pk_list_addr;
r->flags = mark_hidden? 1:0;
*pk_list_addr = r;
}
+ for (node = keyblock; node; node = node->next)
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ && ((pk=node->pkt->pkt.public_key)->pubkey_usage & PUBKEY_USAGE_RENC)
+ && pk->flags.valid
+ && !pk->flags.revoked
+ && !pk->flags.disabled
+ && !pk->has_expired
+ && key_present_in_pk_list (*pk_list_addr, pk))
+ {
+ pk_list_t r;
+
+ r = xmalloc (sizeof *r);
+ r->pk = copy_public_key (NULL, pk);
+ r->next = *pk_list_addr;
+ r->flags = mark_hidden? 1:0; /* FIXME: Use PK_LIST_HIDDEN ? */
+ *pk_list_addr = r;
+ }
+
+
+ release_kbnode (keyblock);
return 0;
}
diff --git a/g10/sig-check.c b/g10/sig-check.c
index ec136024b..09d5a8b5f 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -335,7 +335,8 @@ check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig,
if (r_revoked)
*r_revoked = 0;
- if (pk->timestamp > sig->timestamp )
+ if (pk->timestamp > sig->timestamp
+ && !(parse_key_usage (sig) & PUBKEY_USAGE_RENC))
{
ulong d = pk->timestamp - sig->timestamp;
if ( d < 86400 )