[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-153-gb90506e

by NIIBE Yutaka cvs at cvs.gnupg.org
Tue Feb 12 06:32:09 CET 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  b90506ea220860c89128f002bd593d0462a08d73 (commit)
       via  30f8a3c8736451d8c06ef72521a8da5eabf23016 (commit)
      from  595ab0da666c43a1315a72a1346ee149998d8771 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b90506ea220860c89128f002bd593d0462a08d73
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Feb 6 14:01:23 2013 +0900

    gpg: Implement card_store_subkey again.
    
    * g10/call-agent.h (agent_keytocard): New.
    * g10/call-agent.c (agent_keytocard): New.
    * g10/card-util.c (replace_existing_key_p): Returns 1 when replace.
    (card_generate_subkey): Check return value of replace_existing_key_p.
    (card_store_subkey): Implement again using agent_keytocard.

diff --git a/g10/call-agent.c b/g10/call-agent.c
index ed141da..85a3f28 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -599,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
   return rc;
 }
 
+
+int
+agent_keytocard (const char *hexgrip, int keyno, int force,
+                 const char *serialno, const char *timestamp)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+
+  snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
+            force?"--force ": "", hexgrip, serialno, keyno, timestamp);
+  line[DIM(line)-1] = 0;
+
+  rc = start_agent (NULL, 1);
+  if (rc)
+    return rc;
+
+  rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
+                        NULL, NULL, NULL);
+  if (rc)
+    return rc;
+
+  return rc;
+}
+
 /* Call the agent to retrieve a data object.  This function returns
    the data in the same structure as used by the learn command.  It is
    allowed to update such a structure using this commmand. */
diff --git a/g10/call-agent.h b/g10/call-agent.h
index de05d7a..ab1d41a 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -81,6 +81,10 @@ int agent_learn (struct agent_card_info_s *info);
 /* Update INFO with the attribute NAME. */
 int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
 
+/* Send the KEYTOCARD command. */
+int agent_keytocard (const char *hexgrip, int keyno, int force,
+                     const char *serialno, const char *timestamp);
+
 /* Send a SETATTR command to the SCdaemon. */
 int agent_scd_setattr (const char *name,
                        const unsigned char *value, size_t valuelen,
diff --git a/g10/card-util.c b/g10/card-util.c
index 8358685..75208cc 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -1264,6 +1264,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
       if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
                                   _("Replace existing key? (y/N) ")))
         return -1;
+      return 1;
     }
   return 0;
 }
@@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
       tty_printf(_("Invalid selection.\n"));
     }
 
-  if (replace_existing_key_p (&info, keyno))
+  if (replace_existing_key_p (&info, keyno) < 0)
     {
       err = gpg_error (GPG_ERR_CANCELED);
       goto leave;
@@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
 int
 card_store_subkey (KBNODE node, int use)
 {
-  log_info ("FIXME: card_store_subkey has not yet been implemented\n");
-/*   struct agent_card_info_s info; */
-/*   int okay = 0; */
-/*   int rc; */
-/*   int keyno, i; */
-/*   PKT_secret_key *copied_sk = NULL; */
-/*   PKT_secret_key *sk; */
-/*   size_t n; */
-/*   const char *s; */
-/*   int allow_keyno[3]; */
-/*   unsigned int nbits; */
-
-
-/*   assert (node->pkt->pkttype == PKT_SECRET_KEY */
-/*           || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
-/*   sk = node->pkt->pkt.secret_key; */
-
-/*   if (get_info_for_key_operation (&info)) */
-/*     return 0; */
-
-/*   if (!info.extcap.ki) */
-/*     { */
-/*       tty_printf ("The card does not support the import of keys\n"); */
-/*       tty_printf ("\n"); */
-/*       goto leave; */
-/*     } */
-
-/*   show_card_key_info (&info); */
-
-/*   nbits = nbits_from_sk (sk); */
-
-/*   if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
-/*     { */
-/*       tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
-/*       tty_printf ("\n"); */
-/*       goto leave; */
-/*     } */
-
-/*   allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
-/*   allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
-/*   allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
-
-/*   tty_printf (_("Please select where to store the key:\n")); */
-
-/*   if (allow_keyno[0]) */
-/*     tty_printf (_("   (1) Signature key\n")); */
-/*   if (allow_keyno[1]) */
-/*     tty_printf (_("   (2) Encryption key\n")); */
-/*   if (allow_keyno[2]) */
-/*     tty_printf (_("   (3) Authentication key\n")); */
-
-/*   for (;;)  */
-/*     { */
-/*       char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
-/*                               _("Your selection? ")); */
-/*       cpr_kill_prompt(); */
-/*       if (*answer == CONTROL_D || !*answer) */
-/*         { */
-/*           xfree (answer); */
-/*           goto leave; */
-/*         } */
-/*       keyno = *answer? atoi(answer): 0; */
-/*       xfree(answer); */
-/*       if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
-/*         { */
-/*           if (info.is_v2 && !info.extcap.aac  */
-/*               && info.key_attr[keyno-1].nbits != nbits) */
-/*             { */
-/*               tty_printf ("Key does not match the card's capability.\n"); */
-/*             } */
-/*           else */
-/*             break; /\* Okay. *\/ */
-/*         } */
-/*       else */
-/*         tty_printf(_("Invalid selection.\n")); */
-/*     } */
-
-/*   if (replace_existing_key_p (&info, keyno)) */
-/*     goto leave; */
-
-/*   /\* Unprotect key.  *\/ */
-/*   switch (is_secret_key_protected (sk) ) */
-/*     { */
-/*     case 0: /\* Not protected. *\/ */
-/*       break; */
-/*     case -1: */
-/*       log_error (_("unknown key protection algorithm\n")); */
-/*       goto leave; */
-/*     default: */
-/*       if (sk->protect.s2k.mode == 1001) */
-/*         { */
-/*           log_error (_("secret parts of key are not available\n")); */
-/*           goto leave; */
-/* 	} */
-/*       if (sk->protect.s2k.mode == 1002) */
-/*         { */
-/*           log_error (_("secret key already stored on a card\n")); */
-/*           goto leave; */
-/* 	} */
-/*       /\* We better copy the key before we unprotect it.  *\/ */
-/*       copied_sk = sk = copy_secret_key (NULL, sk); */
-/*       rc = 0/\*check_secret_key (sk, 0)*\/; */
-/*       if (rc) */
-/*         goto leave; */
-/*     } */
-
-/* #warning code save_unprotected_key_to_card */
-/*   /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
-/*   /\* if (rc) *\/ */
-/*   /\*   { *\/ */
-/*   /\*     log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
-/*   /\*     goto leave; *\/ */
-/*   /\*   } *\/ */
-
-/*   /\* Get back to the maybe protected original secret key.  *\/ */
-/*   if (copied_sk) */
-/*     { */
-/*       free_secret_key (copied_sk); */
-/*       copied_sk = NULL;  */
-/*     } */
-/*   sk = node->pkt->pkt.secret_key; */
-
-/*   /\* Get rid of the secret key parameters and store the serial numer. *\/ */
-/*   n = pubkey_get_nskey (sk->pubkey_algo); */
-/*   for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
-/*     { */
-/*       gcry_mpi_release (sk->skey[i]); */
-/*       sk->skey[i] = NULL; */
-/*     } */
-/*   i = pubkey_get_npkey (sk->pubkey_algo); */
-/*   sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
-/*   sk->is_protected = 1; */
-/*   sk->protect.s2k.mode = 1002; */
-/*   s = info.serialno; */
-/*   for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
-/*        sk->protect.ivlen++, s += 2) */
-/*     sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
-
-/*   okay = 1; */
-
-/*  leave: */
-/*   if (copied_sk) */
-/*     free_secret_key (copied_sk); */
-/*   agent_release_card_info (&info); */
-/*   return okay; */
-  return -1;
+  struct agent_card_info_s info;
+  int okay = 0;
+  unsigned int nbits;
+  int allow_keyno[3];
+  int  keyno;
+  PKT_public_key *pk;
+  gpg_error_t err;
+  char *hexgrip;
+  int rc;
+  gnupg_isotime_t timebuf;
+
+  assert (node->pkt->pkttype == PKT_PUBLIC_KEY
+          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+
+  pk = node->pkt->pkt.public_key;
+
+  if (get_info_for_key_operation (&info))
+    return 0;
+
+  if (!info.extcap.ki)
+    {
+      tty_printf ("The card does not support the import of keys\n");
+      tty_printf ("\n");
+      goto leave;
+    }
+
+  nbits = nbits_from_pk (pk);
+
+  if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
+    {
+      tty_printf ("You may only store a 1024 bit RSA key on the card\n");
+      tty_printf ("\n");
+      goto leave;
+    }
+
+  allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
+  allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
+  allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
+
+  tty_printf (_("Please select where to store the key:\n"));
+
+  if (allow_keyno[0])
+    tty_printf (_("   (1) Signature key\n"));
+  if (allow_keyno[1])
+    tty_printf (_("   (2) Encryption key\n"));
+  if (allow_keyno[2])
+    tty_printf (_("   (3) Authentication key\n"));
+
+  for (;;)
+    {
+      char *answer = cpr_get ("cardedit.genkeys.storekeytype",
+                              _("Your selection? "));
+      cpr_kill_prompt();
+      if (*answer == CONTROL_D || !*answer)
+        {
+          xfree (answer);
+          goto leave;
+        }
+      keyno = *answer? atoi(answer): 0;
+      xfree(answer);
+      if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
+        {
+          if (info.is_v2 && !info.extcap.aac
+              && info.key_attr[keyno-1].nbits != nbits)
+            {
+              tty_printf ("Key does not match the card's capability.\n");
+            }
+          else
+            break; /* Okay. */
+        }
+      else
+        tty_printf(_("Invalid selection.\n"));
+    }
+
+  if ((rc = replace_existing_key_p (&info, keyno)) < 0)
+    goto leave;
+
+  err = hexkeygrip_from_pk (pk, &hexgrip);
+  if (err)
+    goto leave;
+
+  epoch2isotime (timebuf, (time_t)pk->timestamp);
+  agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
+
+  if (rc)
+    log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
+  else
+    okay = 1;
+  xfree (hexgrip);
+
+ leave:
+  agent_release_card_info (&info);
+  return okay;
 }
 
 

commit 30f8a3c8736451d8c06ef72521a8da5eabf23016
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Feb 6 14:00:05 2013 +0900

    agent: Add KEYTOCARD command.
    
    * agent/agent.h (divert_writekey, agent_card_writekey): New.
    * agent/call-scd.c (inq_writekey_parms, agent_card_writekey): New.
    * agent/command.c (cmd_keytocard, hlp_keytocard): New.
    (register_commands): Add cmd_keytocard.
    * agent/divert-scd.c (divert_writekey): New.

diff --git a/agent/agent.h b/agent/agent.h
index 8b1cae9..030b295 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -412,6 +412,8 @@ int divert_pkdecrypt (ctrl_t ctrl,
                       char **r_buf, size_t *r_len);
 int divert_generic_cmd (ctrl_t ctrl,
                         const char *cmdline, void *assuan_context);
+int divert_writekey (ctrl_t ctrl, int force, const char *serialno,
+                     const char *id, const char *keydata, size_t keydatalen);
 
 
 /*-- call-scd.c --*/
@@ -445,6 +447,11 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
 int agent_card_readcert (ctrl_t ctrl,
                          const char *id, char **r_buf, size_t *r_buflen);
 int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf);
+int agent_card_writekey (ctrl_t ctrl, int force, const char *serialno,
+                         const char *id, const char *keydata,
+                         size_t keydatalen,
+                         int (*getpin_cb)(void *, const char *, char*, size_t),
+                         void *getpin_cb_arg);
 gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result);
 int agent_card_scd (ctrl_t ctrl, const char *cmdline,
                     int (*getpin_cb)(void *, const char *, char*, size_t),
diff --git a/agent/call-scd.c b/agent/call-scd.c
index 00b34ed..cbe4d1c 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -1050,6 +1050,64 @@ agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
 }
 
 
+struct writekey_parm_s
+{
+  assuan_context_t ctx;
+  int (*getpin_cb)(void *, const char *, char*, size_t);
+  void *getpin_cb_arg;
+  assuan_context_t passthru;
+  int any_inq_seen;
+  /**/
+  const unsigned char *keydata;
+  size_t keydatalen;
+};
+
+/* Handle a KEYDATA inquiry.  Note, we only send the data,
+   assuan_transact takes care of flushing and writing the end */
+static gpg_error_t
+inq_writekey_parms (void *opaque, const char *line)
+{
+  struct writekey_parm_s *parm = opaque;
+
+  if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
+    return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
+  else
+    return inq_needpin (opaque, line);
+}
+
+
+int
+agent_card_writekey (ctrl_t ctrl,  int force, const char *serialno,
+                     const char *id, const char *keydata, size_t keydatalen,
+                     int (*getpin_cb)(void *, const char *, char*, size_t),
+                     void *getpin_cb_arg)
+{
+  int rc;
+  char line[ASSUAN_LINELENGTH];
+  struct writekey_parm_s parms;
+
+  (void)serialno;
+  rc = start_scd (ctrl);
+  if (rc)
+    return rc;
+
+  snprintf (line, DIM(line)-1, "WRITEKEY %s%s", force ? "--force " : "", id);
+  line[DIM(line)-1] = 0;
+  parms.ctx = ctrl->scd_local->ctx;
+  parms.getpin_cb = getpin_cb;
+  parms.getpin_cb_arg = getpin_cb_arg;
+  parms.passthru = 0;
+  parms.any_inq_seen = 0;
+  parms.keydata = keydata;
+  parms.keydatalen = keydatalen;
+
+  rc = assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL,
+                        inq_writekey_parms, &parms, NULL, NULL);
+  if (parms.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
+                             gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
+    rc = cancel_inquire (ctrl, rc);
+  return unlock_scd (ctrl, rc);
+}
 
 /* Type used with the card_getattr_cb.  */
 struct card_getattr_parm_s {
diff --git a/agent/command.c b/agent/command.c
index 715e70a..2844398 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -2119,9 +2119,133 @@ cmd_export_key (assuan_context_t ctx, char *line)
 
   return leave_cmd (ctx, err);
 }
+
+static const char hlp_keytocard[] =
+  "KEYTOCARD [--force] <hexstring_with_keygrip> <serialno> <id> <timestamp>\n"
+  "\n";
+static gpg_error_t
+cmd_keytocard (assuan_context_t ctx, char *line)
+{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  int force;
+  gpg_error_t err = 0;
+  unsigned char grip[20];
+  gcry_sexp_t s_skey = NULL;
+  gcry_sexp_t s_pkey = NULL;
+  unsigned char *keydata;
+  size_t keydatalen, timestamplen;
+  const char *serialno, *timestamp_str, *id;
+  unsigned char *shadow_info;
+  unsigned char *shdkey;
+  time_t timestamp;
+
+  force = has_option (line, "--force");
+  line = skip_options (line);
+
+  err = parse_keygrip (ctx, line, grip);
+  if (err)
+    return err;
+
+  if (agent_key_available (grip))
+    return gpg_error (GPG_ERR_NO_SECKEY);
+
+  line += 40;
+  while (*line && (*line == ' ' || *line == '\t'))
+    line++;
+  serialno = line;
+  while (*line && (*line != ' ' && *line != '\t'))
+    line++;
+  if (!*line)
+    return gpg_error (GPG_ERR_MISSING_VALUE);
+  *line = '\0';
+  line++;
+  while (*line && (*line == ' ' || *line == '\t'))
+    line++;
+  id = line;
+  while (*line && (*line != ' ' && *line != '\t'))
+    line++;
+  if (!*line)
+    return gpg_error (GPG_ERR_MISSING_VALUE);
+  *line = '\0';
+  line++;
+  while (*line && (*line == ' ' || *line == '\t'))
+    line++;
+  timestamp_str = line;
+  while (*line && (*line != ' ' && *line != '\t'))
+    line++;
+  if (*line)
+    *line = '\0';
+  timestamplen = line - timestamp_str;
+  if (timestamplen != 15)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
+                             NULL, CACHE_MODE_IGNORE, NULL, &s_skey, NULL);
+  if (err)
+    return err;
+  if (!s_skey)
+    /* Key is on a smartcard already.  */
+    return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
+
+  keydatalen =  gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
+  keydata = xtrymalloc_secure (keydatalen + 30);
+  if (keydata == NULL)
+    {
+      gcry_sexp_release (s_skey);
+      return gpg_error_from_syserror ();
+    }
 
+  gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
+  gcry_sexp_release (s_skey);
+  /* Add timestamp "created-at" in the private key */
+  timestamp = isotime2epoch (timestamp_str);
+  snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp);
+  keydatalen += 10 + 19 - 1;
+  err = divert_writekey (ctrl, force, serialno, id, keydata, keydatalen);
+  if (err)
+    {
+      xfree (keydata);
+      goto leave;
+    }
+  xfree (keydata);
 
+  err = agent_public_key_from_file (ctrl, grip, &s_pkey);
+  if (err)
+    goto leave;
 
+  shadow_info = make_shadow_info (serialno, id);
+  if (!shadow_info)
+    {
+      err = gpg_error (GPG_ERR_ENOMEM);
+      gcry_sexp_release (s_pkey);
+      goto leave;
+    }
+  keydatalen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
+  keydata = xtrymalloc (keydatalen);
+  if (keydata == NULL)
+    {
+      err = gpg_error_from_syserror ();
+      gcry_sexp_release (s_pkey);
+      goto leave;
+    }
+  gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
+  gcry_sexp_release (s_pkey);
+  err = agent_shadow_key (keydata, shadow_info, &shdkey);
+  xfree (keydata);
+  xfree (shadow_info);
+  if (err)
+    {
+      log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
+      goto leave;
+    }
+
+  keydatalen = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
+  err = agent_write_private_key (grip, shdkey, keydatalen, 1);
+  xfree (shdkey);
+
+ leave:
+  return leave_cmd (ctx, err);
+}
 
 static const char hlp_getval[] =
   "GETVAL <key>\n"
@@ -2674,6 +2798,7 @@ register_commands (assuan_context_t ctx)
     { "KILLAGENT",      cmd_killagent,  hlp_killagent },
     { "RELOADAGENT",    cmd_reloadagent,hlp_reloadagent },
     { "GETINFO",        cmd_getinfo,   hlp_getinfo },
+    { "KEYTOCARD",      cmd_keytocard, hlp_keytocard },
     { NULL }
   };
   int i, rc;
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 5d53891..5fb037e 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -442,6 +442,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)

-----------------------------------------------------------------------

Summary of changes:
 agent/agent.h      |    7 ++
 agent/call-scd.c   |   58 +++++++++++++
 agent/command.c    |  125 +++++++++++++++++++++++++++
 agent/divert-scd.c |    7 ++
 g10/call-agent.c   |   24 +++++
 g10/call-agent.h   |    4 +
 g10/card-util.c    |  242 ++++++++++++++++++++-------------------------------
 7 files changed, 320 insertions(+), 147 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list