aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog6
-rw-r--r--agent/agent.h1
-rw-r--r--agent/cvt-openpgp.c47
-rw-r--r--agent/findkey.c10
-rw-r--r--agent/gpg-agent.c10
-rw-r--r--agent/pksign.c27
-rw-r--r--agent/protect.c6
7 files changed, 89 insertions, 18 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 542695bea..7dace3aef 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -2,6 +2,12 @@
* trustlist.c (read_one_trustfile): Also chop an CR.
+2011-01-21 Werner Koch <[email protected]>
+
+ * pksign.c (do_encode_dsa): Compare MDLEN to bytes.
+
+ * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New.
+
2010-12-02 Werner Koch <[email protected]>
* gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL) [W32CE]: Set to 60
diff --git a/agent/agent.h b/agent/agent.h
index 7716bb0c2..e31b6a78e 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -215,6 +215,7 @@ const char *get_agent_ssh_socket_name (void);
void *get_agent_scd_notify_event (void);
#endif
void agent_sighup_action (void);
+int map_pk_openpgp_to_gcry (int openpgp_algo);
/*-- command.c --*/
gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid);
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index e6a14c436..02c2bc841 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -28,6 +28,13 @@
#include "i18n.h"
#include "cvt-openpgp.h"
+/* Macros for compatibility with older libgcrypt versions. */
+#ifndef HAVE_GCRY_PK_ECDSA
+# define GCRY_PK_ECDH 302
+#endif
+
+
+
/* Helper to pass data via the callback to do_unprotect. */
struct try_do_unprotect_arg_s
@@ -80,6 +87,12 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
"(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
break;
+ case GCRY_PK_ECDSA:
+ case GCRY_PK_ECDH:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(ecc(c%m)(q%m)))", pkey[0], pkey[1]);
+ break;
+
default:
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
break;
@@ -94,7 +107,9 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
/* Convert a secret key given as algorithm id and an array of key
- parameters into our s-expression based format. */
+ parameters into our s-expression based format. Note that
+ PUBKEY_ALGO is a standard id and not an OpenPGP id.
+ */
static gpg_error_t
convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
{
@@ -103,6 +118,9 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
*r_key = NULL;
+ /* FIXME: This is not consistent with the above comment. */
+ pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo);
+
switch (pubkey_algo)
{
case GCRY_PK_DSA:
@@ -128,6 +146,18 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
skey[5]);
break;
+ case GCRY_PK_ECDSA:
+ err = gcry_sexp_build (&s_skey, NULL,
+ "(private-key(ecdsa(c%m)(q%m)(d%m)))",
+ skey[0], skey[1], skey[2]);
+ break;
+
+ case GCRY_PK_ECDH:
+ err = gcry_sexp_build (&s_skey, NULL,
+ "(private-key(ecdh(c%m)(q%m)(p%m)(d%m)))",
+ skey[0], skey[1], skey[2], skey[3]);
+ break;
+
default:
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
break;
@@ -202,6 +232,10 @@ do_unprotect (const char *passphrase,
*r_key = NULL;
+ /* Unfortunately, the OpenPGP PK algorithm numbers need to be
+ re-mapped for Libgcrypt. */
+ pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo);
+
/* Count the actual number of MPIs is in the array and set the
remainder to NULL for easier processing later on. */
for (skeylen = 0; skey[skeylen]; skeylen++)
@@ -219,9 +253,6 @@ do_unprotect (const char *passphrase,
if (gcry_pk_test_algo (pubkey_algo))
{
- /* The algorithm numbers are Libgcrypt numbers but fortunately
- the OpenPGP algorithm numbers map one-to-one to the Libgcrypt
- numbers. */
log_info (_("public key algorithm %d (%s) is not supported\n"),
pubkey_algo, gcry_pk_algo_name (pubkey_algo));
return gpg_error (GPG_ERR_PUBKEY_ALGO);
@@ -1007,7 +1038,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
case GCRY_PK_ELG: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_ELG_E: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_DSA: algoname = "dsa"; npkey = 4; elems = "pqgyx"; break;
- case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break;
+ case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 2; elems = "cqd"; break;
+ case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break;
default: algoname = ""; npkey = 0; elems = NULL; break;
}
assert (!elems || strlen (elems) < DIM (array) );
@@ -1037,7 +1069,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
int format_args_buf_int[1];
void *format_args[10+2];
size_t n;
- gcry_sexp_t tmpkey, tmpsexp;
+ gcry_sexp_t tmpkey, tmpsexp = NULL;
snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
@@ -1085,7 +1117,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
for (i=0; i < DIM (array); i++)
gcry_mpi_release (array[i]);
-
+
return err;
}
-
diff --git a/agent/findkey.c b/agent/findkey.c
index 91fb8c14c..02e938e6e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -726,6 +726,16 @@ key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
algoname = "dsa";
elems = "pqgy";
}
+ else if (n==5 && !memcmp (name, "ecdsa", 5))
+ {
+ algoname = "ecdsa";
+ elems = "cq";
+ }
+ else if (n==4 && !memcmp (name, "ecdh", 4))
+ {
+ algoname = "ecdh";
+ elems = "cqp";
+ }
else if (n==3 && !memcmp (name, "elg", 3))
{
algoname = "elg";
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index ca150b471..db9039278 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -51,6 +51,7 @@
#include "gc-opt-flags.h"
#include "exechelp.h"
#include "asshelp.h"
+#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */
enum cmd_and_opt_values
{ aNull = 0,
@@ -2301,3 +2302,12 @@ check_for_running_agent (int silent, int mode)
assuan_release (ctx);
return 0;
}
+
+/* TODO: it is also in misc, which is not linked with the agent */
+/* FIXME: The agent should not know about openpgp internals - weel
+ except for some stuff in cvt-openpgp. */
+int
+map_pk_openpgp_to_gcry (int algo)
+{
+ return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo));
+}
diff --git a/agent/pksign.c b/agent/pksign.c
index ac5f4e1a0..0414bc347 100644
--- a/agent/pksign.c
+++ b/agent/pksign.c
@@ -113,18 +113,21 @@ get_dsa_qbits (gcry_sexp_t key)
/* Encode a message digest for use with an DSA algorithm. */
static gpg_error_t
-do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
+do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
gcry_sexp_t *r_hash)
{
gpg_error_t err;
gcry_sexp_t hash;
unsigned int qbits;
+ int pkalgo;
*r_hash = NULL;
- if (dsaalgo == GCRY_PK_ECDSA)
+ pkalgo = map_pk_openpgp_to_gcry (dsaalgo);
+
+ if (pkalgo == GCRY_PK_ECDSA)
qbits = gcry_pk_get_nbits (pkey);
- else if (dsaalgo == GCRY_PK_DSA)
+ else if (pkalgo == GCRY_PK_DSA)
qbits = get_dsa_qbits (pkey);
else
return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
@@ -143,20 +146,28 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
if (qbits < 160)
{
log_error (_("%s key uses an unsafe (%u bit) hash\n"),
- gcry_pk_algo_name (dsaalgo), qbits);
+ gcry_pk_algo_name (pkalgo), qbits);
return gpg_error (GPG_ERR_INV_LENGTH);
}
/* Check if we're too short. Too long is safe as we'll
- automatically left-truncate. */
- if (mdlen < qbits/8)
+ * automatically left-truncate.
+ *
+ * This check would require the use of SHA512 with ECDSA 512. I
+ * think this is overkill to fail in this case. Therefore, relax
+ * the check, but only for ECDSA keys. We may need to adjust it
+ * later for general case. (Note that the check is really a bug for
+ * ECDSA 521 as the only hash that matches it is SHA 512, but 512 <
+ * 521 ).
+ */
+ if (mdlen < ((pkalgo==GCRY_PK_ECDSA && qbits > 521) ? 512 : qbits)/8)
{
log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"),
mdlen*8,
gcry_pk_get_nbits (pkey),
- gcry_pk_algo_name (dsaalgo));
+ gcry_pk_algo_name (pkalgo));
/* FIXME: we need to check the requirements for ECDSA. */
- if (mdlen < 20 || dsaalgo == GCRY_PK_DSA)
+ if (mdlen < 20 || pkalgo == GCRY_PK_DSA)
return gpg_error (GPG_ERR_INV_LENGTH);
}
diff --git a/agent/protect.c b/agent/protect.c
index 795d06231..d0a5fe9e3 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -43,7 +43,7 @@
/* A table containing the information needed to create a protected
- private key */
+ private key. */
static struct {
const char *algo;
const char *parmlist;
@@ -52,6 +52,8 @@ static struct {
{ "rsa", "nedpqu", 2, 5 },
{ "dsa", "pqgyx", 4, 4 },
{ "elg", "pgyx", 3, 3 },
+ { "ecdsa","cqd", 2, 2 },
+ { "ecdh", "cqpd", 3, 3 },
{ NULL }
};
@@ -488,7 +490,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
depth--;
hash_end = s;
s++;
- /* skip to the end of the S-exp */
+ /* Skip to the end of the S-expression. */
assert (depth == 1);
rc = sskip (&s, &depth);
if (rc)