aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/card-call-scd.c45
-rw-r--r--tools/gpg-card.c67
-rw-r--r--tools/gpg-card.h3
3 files changed, 77 insertions, 38 deletions
diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c
index 55ecf126e..f7dbfd6ec 100644
--- a/tools/card-call-scd.c
+++ b/tools/card-call-scd.c
@@ -1155,49 +1155,30 @@ scd_writecert (const char *certidstr,
-/* 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)
-{
- gpg_error_t err;
- struct writekey_parm_s *parm = opaque;
-
- if (has_leading_keyword (line, "KEYDATA"))
- {
- err = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
- }
- else
- err = default_inq_cb (parm->dflt, line);
-
- return err;
-}
-
-
-/* Send a WRITEKEY command to the SCdaemon. */
+/* Send a WRITEKEY command to the agent (so that the agent can fetch
+ * the key to write). KEYGRIP is the hexified keygrip of the source
+ * key which will be written to tye slot KEYREF. FORCE must be true
+ * to overwrite an existing key. */
gpg_error_t
-scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
+scd_writekey (const char *keyref, int force, const char *keygrip)
{
gpg_error_t err;
+ struct default_inq_parm_s parm;
char line[ASSUAN_LINELENGTH];
- struct writekey_parm_s parms;
- struct default_inq_parm_s dfltparm;
- memset (&parms, 0, sizeof parms);
- memset (&dfltparm, 0, sizeof dfltparm);
+ memset (&parm, 0, sizeof parm);
err = start_agent (0);
if (err)
return err;
- snprintf (line, sizeof line, "SCD WRITEKEY --force OPENPGP.%d", keyno);
- dfltparm.ctx = agent_ctx;
- parms.dflt = &dfltparm;
- parms.keydata = keydata;
- parms.keydatalen = keydatalen;
-
+ /* Note: We don't send the s/n but "-" because gpg-agent has
+ * currently no use for it. */
+ /* FIXME: For OpenPGP we should provide the creation time. */
+ snprintf (line, sizeof line, "KEYTOCARD%s %s - %s",
+ force? " --force":"", keygrip, keyref);
err = assuan_transact (agent_ctx, line, NULL, NULL,
- inq_writekey_parms, &parms, NULL, NULL);
+ default_inq_cb, &parm, NULL, NULL);
return status_sc_op_failure (err);
}
diff --git a/tools/gpg-card.c b/tools/gpg-card.c
index 3f972fee4..bd450c0bb 100644
--- a/tools/gpg-card.c
+++ b/tools/gpg-card.c
@@ -1667,7 +1667,7 @@ cmd_readcert (card_info_t info, char *argstr)
if (!info)
return print_help
("READCERT CERTREF > FILE\n\n"
- "Read the certificate for key 3 and store it in FILE.",
+ "Read the certificate for key CERTREF and store it in FILE.",
APP_TYPE_OPENPGP, APP_TYPE_PIV, 0);
argstr = skip_options (argstr);
@@ -1719,6 +1719,62 @@ cmd_readcert (card_info_t info, char *argstr)
static gpg_error_t
+cmd_writekey (card_info_t info, char *argstr)
+{
+ gpg_error_t err;
+ int opt_force;
+ char *argv[2];
+ int argc;
+ char *keyref_buffer = NULL;
+ char *keyref;
+ char *keygrip;
+
+ if (!info)
+ return print_help
+ ("WRITEKEY [--force] KEYREF KEYGRIP\n\n"
+ "Write a private key object identified by KEYGRIP to slot KEYREF.\n"
+ "Use --force to overwrite an existing key.",
+ APP_TYPE_OPENPGP, APP_TYPE_PIV, 0);
+
+ opt_force = has_leading_option (argstr, "--force");
+ argstr = skip_options (argstr);
+
+ argc = split_fields (argstr, argv, DIM (argv));
+ if (argc < 2)
+ {
+ err = gpg_error (GPG_ERR_INV_ARG);
+ goto leave;
+ }
+
+ /* Upcase the keyref; prepend cardtype if needed. */
+ keyref = argv[0];
+ if (!strchr (keyref, '.'))
+ keyref_buffer = xstrconcat (app_type_string (info->apptype), ".",
+ keyref, NULL);
+ else
+ keyref_buffer = xstrdup (keyref);
+ ascii_strupr (keyref_buffer);
+ keyref = keyref_buffer;
+
+ /* Get the keygrip. */
+ keygrip = argv[1];
+ if (strlen (keygrip) != 40
+ && !(keygrip[0] == '&' && strlen (keygrip+1) == 40))
+ {
+ log_error (_("Not a valid keygrip (expecting 40 hex digits)\n"));
+ err = gpg_error (GPG_ERR_INV_ARG);
+ goto leave;
+ }
+
+ err = scd_writekey (keyref, opt_force, keygrip);
+
+ leave:
+ xfree (keyref_buffer);
+ return err;
+}
+
+
+static gpg_error_t
cmd_forcesig (card_info_t info)
{
gpg_error_t err;
@@ -2683,7 +2739,7 @@ ask_card_keyattr (int keyno, const struct key_attr *current,
(void)algo;
err = GPG_ERR_NOT_IMPLEMENTED;
goto leave;
- /* FIXME: We need to mve the ask_cure code out to common or
+ /* FIXME: We need to move the ask_cure code out to common or
* provide another sultion. */
/* curve = ask_curve (&algo, NULL, curve); */
/* if (curve) */
@@ -2747,7 +2803,7 @@ do_change_keyattr (int keyno, const struct key_attr *key_attr)
keyno+1, key_attr->algo, key_attr->curve);
else
{
- /* FIXME: Above we use opnepgp algo names but in the error
+ /* FIXME: Above we use openpgp algo names but in the error
* message we use the gcrypt names. We should settle for a
* consistent solution. */
log_error (_("public key algorithm %d (%s) is not supported\n"),
@@ -2918,7 +2974,7 @@ enum cmdids
cmdQUIT, cmdHELP, cmdLIST, cmdRESET, cmdVERIFY,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSALUT, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
- cmdREADCERT, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP,
+ cmdREADCERT, cmdWRITEKEY, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP,
cmdKEYATTR, cmdUIF, cmdAUTH, cmdYUBIKEY,
cmdINVCMD
};
@@ -2958,6 +3014,7 @@ static struct
{ "privatedo", cmdPRIVATEDO, N_("change a private data object")},
{ "readcert", cmdREADCERT, N_("read a certificate from a data object")},
{ "writecert", cmdWRITECERT, N_("store a certificate to a data object")},
+ { "writekey", cmdWRITEKEY, N_("store a private key to a data object")},
{ "yubikey", cmdYUBIKEY, N_("Yubikey management commands")},
{ NULL, cmdINVCMD, NULL }
};
@@ -3084,6 +3141,7 @@ dispatch_command (card_info_t info, const char *orig_command)
case cmdPRIVATEDO: err = cmd_privatedo (info, argstr); break;
case cmdWRITECERT: err = cmd_writecert (info, argstr); break;
case cmdREADCERT: err = cmd_readcert (info, argstr); break;
+ case cmdWRITEKEY: err = cmd_writekey (info, argstr); break;
case cmdFORCESIG: err = cmd_forcesig (info); break;
case cmdGENERATE: err = cmd_generate (info, argstr); break;
case cmdPASSWD: err = cmd_passwd (info, argstr); break;
@@ -3314,6 +3372,7 @@ interactive_loop (void)
case cmdPRIVATEDO: err = cmd_privatedo (info, argstr); break;
case cmdWRITECERT: err = cmd_writecert (info, argstr); break;
case cmdREADCERT: err = cmd_readcert (info, argstr); break;
+ case cmdWRITEKEY: err = cmd_writekey (info, argstr); break;
case cmdFORCESIG: err = cmd_forcesig (info); break;
case cmdGENERATE: err = cmd_generate (info, argstr); break;
case cmdPASSWD: err = cmd_passwd (info, argstr); break;
diff --git a/tools/gpg-card.h b/tools/gpg-card.h
index 03bad7530..3a86a67ec 100644
--- a/tools/gpg-card.h
+++ b/tools/gpg-card.h
@@ -208,8 +208,7 @@ gpg_error_t scd_setattr (const char *name,
const unsigned char *value, size_t valuelen);
gpg_error_t scd_writecert (const char *certidstr,
const unsigned char *certdata, size_t certdatalen);
-gpg_error_t scd_writekey (int keyno,
- const unsigned char *keydata, size_t keydatalen);
+gpg_error_t scd_writekey (const char *keyref, int force, const char *keygrip);
gpg_error_t scd_genkey (const char *keyref, int force, const char *algo,
u32 *createtime);
gpg_error_t scd_serialno (char **r_serialno, const char *demand);