aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--agent/ChangeLog8
-rw-r--r--agent/command.c102
-rw-r--r--agent/protect-tool.c105
3 files changed, 113 insertions, 102 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 7ea18d943..fd0f7105c 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,9 @@
+2010-06-18 Werner Koch <[email protected]>
+
+ * protect-tool.c (store_private_key, rsa_key_check):
+
+ * command.c (cmd_export_key): New.
+
2010-06-15 Werner Koch <[email protected]>
* command.c (cmd_keywrap_key, cmd_import_key): New.
@@ -2652,7 +2658,7 @@ Fri Aug 18 14:27:14 CEST 2000 Werner Koch <[email protected]>
Copyright 2001, 2002, 2003, 2004, 2005,
- 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
diff --git a/agent/command.c b/agent/command.c
index 9bd5ce5c3..3a3b61ba8 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1,6 +1,6 @@
/* command.c - gpg-agent command handler
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
- * 2006, 2008, 2009 Free Software Foundation, Inc.
+ * 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -38,6 +38,8 @@
#include <assuan.h>
#include "i18n.h"
+
+
/* Maximum allowed size of the inquired ciphertext. */
#define MAXLEN_CIPHERTEXT 4096
/* Maximum allowed size of the key parameters. */
@@ -564,7 +566,7 @@ cmd_sigkey (assuan_context_t ctx, char *line)
static const char hlp_setkeydesc[] =
"SETKEYDESC plus_percent_escaped_string\n"
"\n"
- "Set a description to be used for the next PKSIGN or PKDECRYPT\n"
+ "Set a description to be used for the next PKSIGN, PKDECRYPT or EXPORT_KEY\n"
"operation if this operation requires the entry of a passphrase. If\n"
"this command is not used a default text will be used. Note, that\n"
"this description implictly selects the label used for the entry\n"
@@ -573,8 +575,8 @@ static const char hlp_setkeydesc[] =
"\"passphrase\" is used. The description string should not contain\n"
"blanks unless they are percent or '+' escaped.\n"
"\n"
- "The description is only valid for the next PKSIGN or PKDECRYPT\n"
- "operation.";
+ "The description is only valid for the next PKSIGN, PKDECRYPT or\n"
+ "EXPORT_KEY operation.";
static gpg_error_t
cmd_setkeydesc (assuan_context_t ctx, char *line)
{
@@ -1481,7 +1483,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
if (!ctrl->server_local->import_key)
{
- err = gpg_error (GPG_ERR_BAD_KEY);
+ err = gpg_error (GPG_ERR_MISSING_KEY);
goto leave;
}
@@ -1562,15 +1564,97 @@ cmd_import_key (assuan_context_t ctx, char *line)
static const char hlp_export_key[] =
- "EXPORT_KEY\n"
- "\n";
+ "EXPORT_KEY <hexstring_with_keygrip>\n"
+ "\n"
+ "Export a secret key from the key store. The key will be encrypted\n"
+ "using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
+ "using the AESWRAP-128 algorithm. The caller needs to retrieve that key\n"
+ "prior to using this command. The function takes the keygrip as argument.\n";
static gpg_error_t
cmd_export_key (assuan_context_t ctx, char *line)
{
- gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err;
+ unsigned char grip[20];
+ gcry_sexp_t s_skey = NULL;
+ unsigned char *key = NULL;
+ size_t keylen;
+ gcry_cipher_hd_t cipherhd = NULL;
+ unsigned char *wrappedkey = NULL;
+ size_t wrappedkeylen;
+
+ if (!ctrl->server_local->export_key)
+ {
+ err = gpg_error (GPG_ERR_MISSING_KEY);
+ goto leave;
+ }
+
+ err = parse_keygrip (ctx, line, grip);
+ if (err)
+ goto leave;
+
+ if (agent_key_available (grip))
+ {
+ err = gpg_error (GPG_ERR_NO_SECKEY);
+ goto leave;
+ }
+
+ err = agent_key_from_file (ctrl, ctrl->server_local->keydesc, grip,
+ NULL, CACHE_MODE_IGNORE, NULL, &s_skey);
+ if (err)
+ goto leave;
+ if (!s_skey)
+ {
+ /* Key is on a smartcard. Actually we should not see this here
+ because we do not pass a shadow_info variable to the above
+ function, thus it will return this error directly. */
+ err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
+ goto leave;
+ }
+
+ err = make_canon_sexp_pad (s_skey, 1, &key, &keylen);
+ if (err)
+ goto leave;
+ gcry_sexp_release (s_skey);
+ s_skey = NULL;
+
+ err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
+ GCRY_CIPHER_MODE_AESWRAP, 0);
+ if (err)
+ goto leave;
+ err = gcry_cipher_setkey (cipherhd,
+ ctrl->server_local->export_key, KEYWRAP_KEYSIZE);
+ if (err)
+ goto leave;
+ wrappedkeylen = keylen + 8;
+ wrappedkey = xtrymalloc (wrappedkeylen);
+ if (!wrappedkey)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
- /* leave: */
+ err = gcry_cipher_encrypt (cipherhd, wrappedkey, wrappedkeylen, key, keylen);
+ if (err)
+ goto leave;
+ xfree (key);
+ key = NULL;
+ gcry_cipher_close (cipherhd);
+ cipherhd = NULL;
+
+ assuan_begin_confidential (ctx);
+ err = assuan_send_data (ctx, wrappedkey, wrappedkeylen);
+ assuan_end_confidential (ctx);
+
+
+ leave:
+ xfree (wrappedkey);
+ gcry_cipher_close (cipherhd);
+ xfree (key);
+ gcry_sexp_release (s_skey);
+ xfree (ctrl->server_local->keydesc);
+ ctrl->server_local->keydesc = NULL;
return leave_cmd (ctx, err);
}
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 48186d2ac..f3fe1a8d8 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -544,88 +544,6 @@ show_keygrip (const char *fname)
}
-static int
-rsa_key_check (struct rsa_secret_key_s *skey)
-{
- int err = 0;
- gcry_mpi_t t = gcry_mpi_snew (0);
- gcry_mpi_t t1 = gcry_mpi_snew (0);
- gcry_mpi_t t2 = gcry_mpi_snew (0);
- gcry_mpi_t phi = gcry_mpi_snew (0);
-
- /* check that n == p * q */
- gcry_mpi_mul (t, skey->p, skey->q);
- if (gcry_mpi_cmp( t, skey->n) )
- {
- log_error ("RSA oops: n != p * q\n");
- err++;
- }
-
- /* check that p is less than q */
- if (gcry_mpi_cmp (skey->p, skey->q) > 0)
- {
- gcry_mpi_t tmp;
-
- log_info ("swapping secret primes\n");
- tmp = gcry_mpi_copy (skey->p);
- gcry_mpi_set (skey->p, skey->q);
- gcry_mpi_set (skey->q, tmp);
- gcry_mpi_release (tmp);
- /* and must recompute u of course */
- gcry_mpi_invm (skey->u, skey->p, skey->q);
- }
-
- /* check that e divides neither p-1 nor q-1 */
- gcry_mpi_sub_ui (t, skey->p, 1 );
- gcry_mpi_div (NULL, t, t, skey->e, 0);
- if (!gcry_mpi_cmp_ui( t, 0) )
- {
- log_error ("RSA oops: e divides p-1\n");
- err++;
- }
- gcry_mpi_sub_ui (t, skey->q, 1);
- gcry_mpi_div (NULL, t, t, skey->e, 0);
- if (!gcry_mpi_cmp_ui( t, 0))
- {
- log_info ( "RSA oops: e divides q-1\n" );
- err++;
- }
-
- /* check that d is correct. */
- gcry_mpi_sub_ui (t1, skey->p, 1);
- gcry_mpi_sub_ui (t2, skey->q, 1);
- gcry_mpi_mul (phi, t1, t2);
- gcry_mpi_invm (t, skey->e, phi);
- if (gcry_mpi_cmp (t, skey->d))
- { /* no: try universal exponent. */
- gcry_mpi_gcd (t, t1, t2);
- gcry_mpi_div (t, NULL, phi, t, 0);
- gcry_mpi_invm (t, skey->e, t);
- if (gcry_mpi_cmp (t, skey->d))
- {
- log_error ("RSA oops: bad secret exponent\n");
- err++;
- }
- }
-
- /* check for correctness of u */
- gcry_mpi_invm (t, skey->p, skey->q);
- if (gcry_mpi_cmp (t, skey->u))
- {
- log_info ( "RSA oops: bad u parameter\n");
- err++;
- }
-
- if (err)
- log_info ("RSA secret key check failed\n");
-
- gcry_mpi_release (t);
- gcry_mpi_release (t1);
- gcry_mpi_release (t2);
- gcry_mpi_release (phi);
-
- return err? -1:0;
-}
#if 0
/* A callback used by p12_parse to return a certificate. */
@@ -789,6 +707,7 @@ import_p12_file (const char *fname)
+#if 0
static gcry_mpi_t *
sexp_to_kparms (gcry_sexp_t sexp)
{
@@ -842,20 +761,20 @@ sexp_to_kparms (gcry_sexp_t sexp)
gcry_sexp_release (list);
return array;
}
-
+#endif
/* Check whether STRING is a KEYGRIP, i.e has the correct length and
does only consist of uppercase hex characters. */
-static int
-is_keygrip (const char *string)
-{
- int i;
+/* static int */
+/* is_keygrip (const char *string) */
+/* { */
+/* int i; */
- for(i=0; string[i] && i < 41; i++)
- if (!strchr("01234567890ABCDEF", string[i]))
- return 0;
- return i == 40;
-}
+/* for(i=0; string[i] && i < 41; i++) */
+/* if (!strchr("01234567890ABCDEF", string[i])) */
+/* return 0; */
+/* return i == 40; */
+/* } */
#if 0
@@ -1195,6 +1114,7 @@ release_passphrase (char *pw)
}
}
+#if 0
static int
store_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force)
@@ -1257,3 +1177,4 @@ store_private_key (const unsigned char *grip,
xfree (fname);
return 0;
}
+#endif