gpg: Fix detection of the AEAD feature flag.
[gnupg.git] / g10 / getkey.c
index e31e023..fe64835 100644 (file)
@@ -144,7 +144,7 @@ static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
                   kbnode_t *ret_keyblock, kbnode_t *ret_found_key);
 static kbnode_t finish_lookup (kbnode_t keyblock,
                                unsigned int req_usage, int want_exact,
-                               unsigned int *r_flags);
+                               int want_secret, unsigned int *r_flags);
 static void print_status_key_considered (kbnode_t keyblock, unsigned int flags);
 
 
@@ -1743,7 +1743,7 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
       /* Warning: node flag bits 0 and 1 should be preserved by
        * merge_selfsigs.  FIXME: Check whether this still holds. */
       merge_selfsigs (ctrl, keyblock);
-      found_key = finish_lookup (keyblock, pk->req_usage, 0, &infoflags);
+      found_key = finish_lookup (keyblock, pk->req_usage, 0, 0, &infoflags);
       print_status_key_considered (keyblock, infoflags);
       if (found_key)
         pk_from_block (pk, keyblock, found_key);
@@ -1810,6 +1810,8 @@ get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
       ctx.items[0].mode = fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16
        : KEYDB_SEARCH_MODE_FPR20;
       memcpy (ctx.items[0].u.fpr, fprint, fprint_len);
+      if (pk)
+        ctx.req_usage = pk->req_usage;
       rc = lookup (ctrl, &ctx, 0, &kb, &found_key);
       if (!rc && pk)
        pk_from_block (pk, kb, found_key);
@@ -2443,8 +2445,8 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
 {
   PKT_user_id *uid = uidnode->pkt->pkt.user_id;
   PKT_signature *sig = signode->pkt->pkt.signature;
-  const byte *p, *sym, *hash, *zip;
-  size_t n, nsym, nhash, nzip;
+  const byte *p, *sym, *aead, *hash, *zip;
+  size_t n, nsym, naead, nhash, nzip;
 
   sig->flags.chosen_selfsig = 1;/* We chose this one. */
   uid->created = 0;            /* Not created == invalid. */
@@ -2499,6 +2501,9 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
   p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM, &n);
   sym = p;
   nsym = p ? n : 0;
+  p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_AEAD, &n);
+  aead = p;
+  naead = p ? n : 0;
   p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH, &n);
   hash = p;
   nhash = p ? n : 0;
@@ -2507,7 +2512,7 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
   nzip = p ? n : 0;
   if (uid->prefs)
     xfree (uid->prefs);
-  n = nsym + nhash + nzip;
+  n = nsym + naead + nhash + nzip;
   if (!n)
     uid->prefs = NULL;
   else
@@ -2519,6 +2524,11 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
          uid->prefs[n].type = PREFTYPE_SYM;
          uid->prefs[n].value = *sym++;
        }
+      for (; naead; naead--, n++)
+       {
+         uid->prefs[n].type = PREFTYPE_AEAD;
+         uid->prefs[n].value = *aead++;
+       }
       for (; nhash; nhash--, n++)
        {
          uid->prefs[n].type = PREFTYPE_HASH;
@@ -2539,6 +2549,12 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
   if (p && n && (p[0] & 0x01))
     uid->flags.mdc = 1;
 
+  /* See whether we have the AEAD feature.  */
+  uid->flags.aead = 0;
+  p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n);
+  if (p && n && (p[0] & 0x02))
+    uid->flags.aead = 1;
+
   /* And the keyserver modify flag.  */
   uid->flags.ks_modify = 1;
   p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n);
@@ -3357,6 +3373,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
   PKT_public_key *main_pk;
   prefitem_t *prefs;
   unsigned int mdc_feature;
+  unsigned int aead_feature;
 
   if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
     {
@@ -3418,7 +3435,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
    * all preferences.
    * Do a similar thing for the MDC feature flag.  */
   prefs = NULL;
-  mdc_feature = 0;
+  mdc_feature = aead_feature = 0;
   for (k = keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next)
     {
       if (k->pkt->pkttype == PKT_USER_ID
@@ -3427,6 +3444,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
        {
          prefs = k->pkt->pkt.user_id->prefs;
          mdc_feature = k->pkt->pkt.user_id->flags.mdc;
+         aead_feature = k->pkt->pkt.user_id->flags.aead;
          break;
        }
     }
@@ -3440,6 +3458,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
            xfree (pk->prefs);
          pk->prefs = copy_prefs (prefs);
          pk->flags.mdc = mdc_feature;
+         pk->flags.aead = aead_feature;
        }
     }
 }
@@ -3494,7 +3513,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
  */
 static kbnode_t
 finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
-               unsigned int *r_flags)
+               int want_secret, unsigned int *r_flags)
 {
   kbnode_t k;
 
@@ -3636,6 +3655,13 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
              continue;
            }
 
+          if (want_secret && agent_probe_secret_key (NULL, pk))
+            {
+              if (DBG_LOOKUP)
+                log_debug ("\tno secret key\n");
+              continue;
+            }
+
          if (DBG_LOOKUP)
            log_debug ("\tsubkey might be fine\n");
          /* In case a key has a timestamp of 0 set, we make sure
@@ -3823,7 +3849,7 @@ lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
        * merge_selfsigs.  */
       merge_selfsigs (ctrl, keyblock);
       found_key = finish_lookup (keyblock, ctx->req_usage, ctx->exact,
-                                 &infoflags);
+                                 want_secret, &infoflags);
       print_status_key_considered (keyblock, infoflags);
       if (found_key)
        {
@@ -4110,15 +4136,20 @@ get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
  *********************************************/
 
 /* Return a string with a printable representation of the user_id.
- * this string must be freed by xfree.   */
+ * this string must be freed by xfree.  If R_NOUID is not NULL it is
+ * set to true if a user id was not found; otherwise to false.  */
 static char *
-get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len)
+get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len,
+                    int *r_nouid)
 {
   user_id_db_t r;
   keyid_list_t a;
   int pass = 0;
   char *p;
 
+  if (r_nouid)
+    *r_nouid = 0;
+
   /* Try it two times; second pass reads from the database.  */
   do
     {
@@ -4165,6 +4196,8 @@ get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len)
   else
     p = xasprintf ("%s [?]", keystr (keyid));
 
+  if (r_nouid)
+    *r_nouid = 1;
   if (r_len)
     *r_len = strlen (p);
   return p;
@@ -4174,7 +4207,7 @@ get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len)
 char *
 get_user_id_string_native (ctrl_t ctrl, u32 * keyid)
 {
-  char *p = get_user_id_string (ctrl, keyid, 0, NULL);
+  char *p = get_user_id_string (ctrl, keyid, 0, NULL, NULL);
   char *p2 = utf8_to_native (p, strlen (p), 0);
   xfree (p);
   return p2;
@@ -4184,15 +4217,15 @@ get_user_id_string_native (ctrl_t ctrl, u32 * keyid)
 char *
 get_long_user_id_string (ctrl_t ctrl, u32 * keyid)
 {
-  return get_user_id_string (ctrl, keyid, 1, NULL);
+  return get_user_id_string (ctrl, keyid, 1, NULL, NULL);
 }
 
 
 /* Please try to use get_user_byfpr instead of this one.  */
 char *
-get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn)
+get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid)
 {
-  return get_user_id_string (ctrl, keyid, 2, rn);
+  return get_user_id_string (ctrl, keyid, 2, rn, r_nouid);
 }
 
 
@@ -4201,7 +4234,7 @@ char *
 get_user_id_native (ctrl_t ctrl, u32 *keyid)
 {
   size_t rn;
-  char *p = get_user_id (ctrl, keyid, &rn);
+  char *p = get_user_id (ctrl, keyid, &rn, NULL);
   char *p2 = utf8_to_native (p, rn, 0);
   xfree (p);
   return p2;