diff options
Diffstat (limited to '')
-rw-r--r-- | agent/ChangeLog | 8 | ||||
-rw-r--r-- | agent/command.c | 102 | ||||
-rw-r--r-- | agent/protect-tool.c | 105 |
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 |