agent: Send back all public keys for available cards.
[gnupg.git] / agent / divert-scd.c
index f176a6b..7331f58 100644 (file)
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -44,7 +44,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
 
   *r_kid = NULL;
 
-  rc = parse_shadow_info (shadow_info, &want_sn, &want_kid);
+  rc = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
   if (rc)
     return rc;
 
@@ -58,7 +58,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
 
   for (;;)
     {
-      rc = agent_card_serialno (ctrl, &serialno);
+      rc = agent_card_serialno (ctrl, &serialno, want_sn);
       if (!rc)
         {
           log_debug ("detected card with S/N %s\n", serialno);
@@ -72,11 +72,17 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
               return 0; /* yes, we have the correct card */
             }
         }
+      else if (gpg_err_code (rc) == GPG_ERR_ENODEV)
+        {
+          log_debug ("no device present\n");
+          rc = 0;
+          no_card = 1;
+        }
       else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
         {
           log_debug ("no card present\n");
           rc = 0;
-          no_card = 1;
+          no_card = 2;
         }
       else
         {
@@ -89,9 +95,9 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
                     "%s:%%0A%%0A"
                     "  \"%.*s\"",
                         no_card
-                        ? _("Please insert the card with serial number")
-                        : _("Please remove the current card and "
-                            "insert the one with serial number"),
+                        ? L_("Please insert the card with serial number")
+                        : L_("Please remove the current card and "
+                             "insert the one with serial number"),
                     want_sn_displen, want_sn) < 0)
             {
               rc = out_of_core ();
@@ -99,6 +105,10 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
           else
             {
               rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
+             if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
+                 gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
+               rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+
               xfree (desc);
             }
         }
@@ -197,19 +207,19 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
       for (s=info+1; s < ends; s++)
         {
           if (*s == 'A')
-            prompt = _("Admin PIN");
+            prompt = L_("Admin PIN");
           else if (*s == 'P')
             {
               /* TRANSLATORS: A PUK is the Personal Unblocking Code
                  used to unblock a PIN. */
-              prompt = _("PUK");
+              prompt = L_("PUK");
               is_puk = 1;
             }
           else if (*s == 'N')
             newpin = 1;
           else if (*s == 'R')
             {
-              prompt = _("Reset Code");
+              prompt = L_("Reset Code");
               resetcode = 1;
             }
         }
@@ -219,8 +229,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
   else if (info && *info == '|')
     log_debug ("pin_cb called without proper PIN info hack\n");
 
-  /* If BUF has been passed as NULL, we are in keypad mode: The
-     callback opens the popup and immediatley returns. */
+  /* If BUF has been passed as NULL, we are in pinpad mode: The
+     callback opens the popup and immediately returns. */
   if (!buf)
     {
       if (maxbuf == 0) /* Close the pinentry. */
@@ -235,7 +245,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
               char *desc;
 
               if ( asprintf (&desc,
-                             _("%s%%0A%%0AUse the reader's keypad for input."),
+                             L_("%s%%0A%%0AUse the reader's pinpad for input."),
                              info) < 0 )
                 rc = gpg_error_from_syserror ();
               else
@@ -266,7 +276,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
 
   if (any_flags)
     {
-      rc = agent_askpin (ctrl, info, prompt, again_text, pi);
+      rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL, 0);
       again_text = NULL;
       if (!rc && newpin)
         {
@@ -284,18 +294,18 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
           pi2->max_tries = 1;
           rc = agent_askpin (ctrl,
                              (resetcode?
-                              _("Repeat this Reset Code"):
+                              L_("Repeat this Reset Code"):
                               is_puk?
-                              _("Repeat this PUK"):
-                              _("Repeat this PIN")),
-                             prompt, NULL, pi2);
+                              L_("Repeat this PUK"):
+                              L_("Repeat this PIN")),
+                             prompt, NULL, pi2, NULL, 0);
           if (!rc && strcmp (pi->pin, pi2->pin))
             {
               again_text = (resetcode?
-                            N_("Reset Code not correctly repeated; try again"):
+                            L_("Reset Code not correctly repeated; try again"):
                             is_puk?
-                            N_("PUK not correctly repeated; try again"):
-                            N_("PIN not correctly repeated; try again"));
+                            L_("PUK not correctly repeated; try again"):
+                            L_("PIN not correctly repeated; try again"));
               xfree (pi2);
               xfree (pi);
               goto again;
@@ -307,12 +317,12 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
     {
       char *desc;
       if ( asprintf (&desc,
-                     _("Please enter the PIN%s%s%s to unlock the card"),
-                     info? " (`":"",
+                     L_("Please enter the PIN%s%s%s to unlock the card"),
+                     info? " (":"",
                      info? info:"",
-                     info? "')":"") < 0)
+                     info? ")":"") < 0)
         desc = NULL;
-      rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
+      rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL, 0);
       xfree (desc);
     }
 
@@ -331,7 +341,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
 int
 divert_pksign (ctrl_t ctrl,
                const unsigned char *digest, size_t digestlen, int algo,
-               const unsigned char *shadow_info, unsigned char **r_sig)
+               const unsigned char *shadow_info, unsigned char **r_sig,
+               size_t *r_siglen)
 {
   int rc;
   char *kid;
@@ -365,7 +376,10 @@ divert_pksign (ctrl_t ctrl,
     }
 
   if (!rc)
-    *r_sig = sigval;
+    {
+      *r_sig = sigval;
+      *r_siglen = siglen;
+    }
 
   xfree (kid);
 
@@ -375,12 +389,13 @@ divert_pksign (ctrl_t ctrl,
 
 /* Decrypt the the value given asn an S-expression in CIPHER using the
    key identified by SHADOW_INFO and return the plaintext in an
-   allocated buffer in R_BUF.  */
+   allocated buffer in R_BUF.  The padding information is stored at
+   R_PADDING with -1 for not known.  */
 int
 divert_pkdecrypt (ctrl_t ctrl,
                   const unsigned char *cipher,
                   const unsigned char *shadow_info,
-                  char **r_buf, size_t *r_len)
+                  char **r_buf, size_t *r_len, int *r_padding)
 {
   int rc;
   char *kid;
@@ -391,6 +406,8 @@ divert_pkdecrypt (ctrl_t ctrl,
   char *plaintext;
   size_t plaintextlen;
 
+  *r_padding = -1;
+
   s = cipher;
   if (*s != '(')
     return gpg_error (GPG_ERR_INV_SEXP);
@@ -406,17 +423,45 @@ divert_pkdecrypt (ctrl_t ctrl,
   n = snext (&s);
   if (!n)
     return gpg_error (GPG_ERR_INV_SEXP);
-  if (!smatch (&s, n, "rsa"))
+  if (smatch (&s, n, "rsa"))
+    {
+      if (*s != '(')
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+      s++;
+      n = snext (&s);
+      if (!n)
+        return gpg_error (GPG_ERR_INV_SEXP);
+      if (!smatch (&s, n, "a"))
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+      n = snext (&s);
+    }
+  else if (smatch (&s, n, "ecdh"))
+    {
+      if (*s != '(')
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+      s++;
+      n = snext (&s);
+      if (!n)
+        return gpg_error (GPG_ERR_INV_SEXP);
+      if (smatch (&s, n, "s"))
+        {
+          n = snext (&s);
+          s += n;
+          if (*s++ != ')')
+            return gpg_error (GPG_ERR_INV_SEXP);
+          if (*s++ != '(')
+            return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+          n = snext (&s);
+          if (!n)
+            return gpg_error (GPG_ERR_INV_SEXP);
+        }
+      if (!smatch (&s, n, "e"))
+        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
+      n = snext (&s);
+    }
+  else
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-  if (*s != '(')
-    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-  s++;
-  n = snext (&s);
-  if (!n)
-    return gpg_error (GPG_ERR_INV_SEXP);
-  if (!smatch (&s, n, "a"))
-    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-  n = snext (&s);
+
   if (!n)
     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
   ciphertext = s;
@@ -428,7 +473,7 @@ divert_pkdecrypt (ctrl_t ctrl,
 
   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
                              ciphertext, ciphertextlen,
-                             &plaintext, &plaintextlen);
+                             &plaintext, &plaintextlen, r_padding);
   if (!rc)
     {
       *r_buf = plaintext;
@@ -438,6 +483,13 @@ divert_pkdecrypt (ctrl_t ctrl,
   return rc;
 }
 
+int
+divert_writekey (ctrl_t ctrl, int force, const char *serialno,
+                 const char *id, const char *keydata, size_t keydatalen)
+{
+  return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
+                              getpin_cb, ctrl);
+}
 
 int
 divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)