gpg: First take on PKT_ENCRYPTED_AEAD.
[gnupg.git] / agent / learncard.c
index c60b3f4..abe1dd0 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>
@@ -133,7 +133,7 @@ kpinfo_cb (void *opaque, const char *line)
   char *p;
 
   if (parm->error)
-    return; /* no need to gather data after an error coccured */
+    return; /* no need to gather data after an error occurred */
 
   if ((parm->error = agent_write_status (parm->ctrl, "PROGRESS",
                                          "learncard", "k", "0", "0", NULL)))
@@ -190,7 +190,7 @@ certinfo_cb (void *opaque, const char *line)
   char *p, *pend;
 
   if (parm->error)
-    return; /* no need to gather data after an error coccured */
+    return; /* no need to gather data after an error occurred */
 
   if ((parm->error = agent_write_status (parm->ctrl, "PROGRESS",
                                          "learncard", "c", "0", "0", NULL)))
@@ -232,7 +232,7 @@ sinfo_cb (void *opaque, const char *keyword, size_t keywordlen,
   SINFO item;
 
   if (sparm->error)
-    return; /* no need to gather data after an error coccured */
+    return; /* no need to gather data after an error occurred */
 
   item = xtrycalloc (1, sizeof *item + keywordlen + 1 + strlen (data));
   if (!item)
@@ -296,17 +296,16 @@ send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context)
   return 0;
 }
 
-/* Perform the learn operation.  If ASSUAN_CONTEXT is not NULL all new
-   certificates are send back via Assuan.  */
+/* Perform the learn operation.  If ASSUAN_CONTEXT is not NULL and
+   SEND is true all new certificates are send back via Assuan.  */
 int
-agent_handle_learn (ctrl_t ctrl, void *assuan_context)
+agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
 {
   int rc;
-
   struct kpinfo_cb_parm_s parm;
   struct certinfo_cb_parm_s cparm;
   struct sinfo_cb_parm_s sparm;
-  char *serialno = NULL;
+  const char *serialno = NULL;
   KEYPAIR_INFO item;
   SINFO sitem;
   unsigned char grip[20];
@@ -329,11 +328,6 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
   parm.ctrl = ctrl;
   cparm.ctrl = ctrl;
 
-  /* Check whether a card is present and get the serial number */
-  rc = agent_card_serialno (ctrl, &serialno);
-  if (rc)
-    goto leave;
-
   /* Now gather all the available info. */
   rc = agent_card_learn (ctrl, kpinfo_cb, &parm, certinfo_cb, &cparm,
                          sinfo_cb, &sparm);
@@ -345,17 +339,23 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
       goto leave;
     }
 
-  log_info ("card has S/N: %s\n", serialno);
-
   /* Pass on all the collected status information. */
-  if (assuan_context)
+  for (sitem = sparm.info; sitem; sitem = sitem->next)
     {
-      for (sitem = sparm.info; sitem; sitem = sitem->next)
-        {
-          assuan_write_status (assuan_context, sitem->keyword, sitem->data);
-        }
+      if (!strcmp (sitem->keyword, "SERIALNO"))
+        serialno = sitem->data;
+      if (assuan_context)
+        assuan_write_status (assuan_context, sitem->keyword, sitem->data);
+    }
+
+  if (!serialno)
+    {
+      rc = GPG_ERR_NOT_FOUND;
+      goto leave;
     }
 
+  log_info ("card has S/N: %s\n", serialno);
+
   /* Write out the certificates in a standard order. */
   for (i=0; certtype_list[i] != -1; i++)
     {
@@ -369,7 +369,7 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
             log_info ("          id: %s    (type=%d)\n",
                       citem->id, citem->type);
 
-          if (assuan_context)
+          if (assuan_context && send)
             {
               rc = send_cert_back (ctrl, citem->id, assuan_context);
               if (rc)
@@ -381,8 +381,7 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
 
   for (item = parm.info; item; item = item->next)
     {
-      unsigned char *pubkey, *shdkey;
-      size_t n;
+      unsigned char *pubkey;
 
       if (opt.verbose)
         log_info ("          id: %s    (grip=%s)\n", item->id, item->hexgrip);
@@ -399,7 +398,7 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
       for (p=item->hexgrip, i=0; i < 20; p += 2, i++)
         grip[i] = xtoi_2 (p);
 
-      if (!agent_key_available (grip))
+      if (!force && !agent_key_available (grip))
         continue; /* The key is already available. */
 
       /* Unknown key - store it. */
@@ -410,38 +409,15 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
           goto leave;
         }
 
-      {
-        unsigned char *shadow_info = make_shadow_info (serialno, item->id);
-        if (!shadow_info)
-          {
-            rc = gpg_error (GPG_ERR_ENOMEM);
-            xfree (pubkey);
-            goto leave;
-          }
-        rc = agent_shadow_key (pubkey, shadow_info, &shdkey);
-        xfree (shadow_info);
-      }
+      rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force);
       xfree (pubkey);
       if (rc)
-        {
-          log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
-          goto leave;
-        }
-      n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
-      assert (n);
-
-      rc = agent_write_private_key (grip, shdkey, n, 0);
-      xfree (shdkey);
-      if (rc)
-        {
-          log_error ("error writing key: %s\n", gpg_strerror (rc));
-          goto leave;
-        }
+        goto leave;
 
       if (opt.verbose)
-        log_info ("stored\n");
+        log_info ("          id: %s - shadow key created\n", item->id);
 
-      if (assuan_context)
+      if (assuan_context && send)
         {
           CERTINFO citem;
 
@@ -462,7 +438,6 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context)
 
 
  leave:
-  xfree (serialno);
   release_keypair_info (parm.info);
   release_certinfo (cparm.info);
   release_sinfo (sparm.info);