1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Sample ECC keys and message do now work.

Import and export of secret keys does now work.  Encryption has been
fixed to be compatible with the sample messages.

This version tests for new Libgcrypt function and thus needs to be
build with a new Libgcrypt installed.
This commit is contained in:
Werner Koch 2011-02-02 15:48:54 +01:00
parent e0d4139e19
commit 4659c923a0
19 changed files with 692 additions and 356 deletions

View File

@ -1,3 +1,7 @@
2011-02-01 Werner Koch <wk@g10code.com>
* configure.ac (HAVE_GCRY_PK_GET_CURVE): Define if availabale.
2011-01-20 Werner Koch <wk@g10code.com>
* configure.ac (AC_CONFIG_FILES): Remove keyserver/.

View File

@ -1,5 +1,12 @@
2011-02-02 Werner Koch <wk@g10code.com>
* cvt-openpgp.c (convert_secret_key): Remove algo mapping.
2011-01-31 Werner Koch <wk@g10code.com>
* cvt-openpgp.c (convert_to_openpgp): Adjust to reverted Libgcrypt
ABI.
* protect.c (protect_info): Adjust ECDSA and ECDH parameter names.
Add "ecc".
* findkey.c (key_parms_from_sexp): Ditto.

View File

@ -87,10 +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:
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]);
"(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
pkey[0], pkey[1], pkey[2], pkey[3], pkey[4],
pkey[5]);
break;
default:
@ -108,8 +110,7 @@ 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. Note that
PUBKEY_ALGO is a standard id and not an OpenPGP id.
*/
PUBKEY_ALGO has an gcrypt algorithm number. */
static gpg_error_t
convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
{
@ -118,9 +119,6 @@ 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:
@ -147,15 +145,15 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
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:
/* Although our code would work with "ecc" we explicitly use
"ecdh" or "ecdsa" to implicitly set the key capabilities. */
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]);
"(private-key(%s(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)"
"(d%m)))",
pubkey_algo == GCRY_PK_ECDSA?"ecdsa":"ecdh",
skey[0], skey[1], skey[2], skey[3], skey[4],
skey[5], skey[6]);
break;
default:
@ -1038,8 +1036,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 = 2; elems = "cqd"; break;
case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break;
case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break;
case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 6; elems = "pabgnqd"; break;
default: algoname = ""; npkey = 0; elems = NULL; break;
}
assert (!elems || strlen (elems) < DIM (array) );

View File

@ -42,6 +42,12 @@
#ifndef GPG_ERR_FULLY_CANCELED
#define GPG_ERR_FULLY_CANCELED 198
#endif
#ifndef GPG_ERR_INV_CURVE
#define GPG_ERR_INV_CURVE 187
#endif
#ifndef GPG_ERR_UNKNOWN_CURVE
#define GPG_ERR_UNKNOWN_CURVE 188
#endif
/* Hash function used with libksba. */

View File

@ -742,6 +742,7 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
have_libgcrypt=yes,have_libgcrypt=no)
# fixme: We can remove the next two checks if we require libgcrypt 1.5.
AC_CACHE_CHECK([whether Libgcrypt support ECDH], gnupg_cv_gcry_pk_ecdh,
[ _gnupg_gcry_save_cflags=$CFLAGS
CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
@ -756,6 +757,21 @@ if test "$gnupg_cv_gcry_pk_ecdh" = yes; then
[Define if gcrypt.h has the enum value for ECDH.])
fi
AC_CACHE_CHECK([whether Libgcrypt has gcry_pk_get_curve],
gnupg_cv_gcry_pk_get_curve,
[ _gnupg_gcry_save_cflags=$CFLAGS
CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
AC_TRY_COMPILE(
[#include <gcrypt.h>],
[ return gcry_pk_get_curve (NULL, 0, NULL); ],
gnupg_cv_gcry_pk_get_curve=yes,
gnupg_cv_gcry_pk_get_curve=no)
CFLAGS=$_gnupg_gcry_save_cflags])
if test "$gnupg_cv_gcry_pk_get_curve" = yes; then
AC_DEFINE([HAVE_GCRY_PK_GET_CURVE], 1,
[Define if gcrypt.h has gcry_pk_get_curve.])
fi
#
# libassuan is used for IPC

View File

@ -1,3 +1,18 @@
2011-02-02 Werner Koch <wk@g10code.com>
* import.c (transfer_secret_keys): Make sure keyids are available.
* keyid.c (hash_public_key): Adjust for the ECC case.
2011-02-01 Werner Koch <wk@g10code.com>
* import.c (transfer_secret_keys): Implement ECC case.
* gpg.c (main): Call setup_libgcrypt_logging.
* keygen.c (gpg_curve_to_oid): New.
(ecckey_from_sexp): Factor curve name mapping out to new function.
2011-01-31 Werner Koch <wk@g10code.com>
* misc.c (make_flagged_int, openpgp_oid_from_str)

View File

@ -106,8 +106,8 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
byte *secret_x;
int secret_x_size;
unsigned int nbits;
const unsigned char *kdf_params;
size_t kdf_params_size;
const unsigned char *kek_params;
size_t kek_params_size;
int kdf_hash_algo;
int kdf_encr_algo;
unsigned char message[256];
@ -158,18 +158,18 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
*/
if (!gcry_mpi_get_flag (pkey[2], GCRYMPI_FLAG_OPAQUE))
return GPG_ERR_BUG;
kdf_params = gcry_mpi_get_opaque (pkey[2], &nbits);
kdf_params_size = (nbits+7)/8;
kek_params = gcry_mpi_get_opaque (pkey[2], &nbits);
kek_params_size = (nbits+7)/8;
if (DBG_CIPHER)
log_printhex ("ecdh KDF params:", kdf_params, kdf_params_size);
log_printhex ("ecdh KDF params:", kek_params, kek_params_size);
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1)
if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
return GPG_ERR_BAD_PUBKEY;
kdf_hash_algo = kdf_params[2];
kdf_encr_algo = kdf_params[3];
kdf_hash_algo = kek_params[2];
kdf_encr_algo = kek_params[3];
if (DBG_CIPHER)
log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
@ -207,11 +207,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
return err;
if(DBG_CIPHER)
log_printhex ("ecdh KDF message params are:",
kdf_params, kdf_params_size );
log_printhex ("ecdh KDF message params are:", message, message_size);
}
/* Derive a KEK (key wrapping key) using kdf_params and secret_x. */
/* Derive a KEK (key wrapping key) using MESSAGE and SECRET_X. */
{
gcry_md_hd_t h;
int old_size;
@ -222,7 +221,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
kdf_hash_algo, gpg_strerror (err));
gcry_md_write(h, "\x00\x00\x00\x01", 4); /* counter = 1 */
gcry_md_write(h, secret_x, secret_x_size); /* x of the point X */
gcry_md_write(h, kdf_params, kdf_params_size);/* KDF parameters */
gcry_md_write(h, message, message_size);/* KDF parameters */
gcry_md_final (h);
@ -453,5 +452,3 @@ pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN],
sk_fp, data/*encr data as an MPI*/,
skey, result);
}

View File

@ -354,7 +354,7 @@ canon_pubkey_algo (int algo)
/* Use the key transfer format given in S_PGP to create the secinfo
structure in PK and chnage the parameter array in PK to include the
structure in PK and change the parameter array in PK to include the
secret parameters. */
static gpg_error_t
transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
@ -460,6 +460,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
|| gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
|| !npkey || npkey >= nskey || nskey > PUBKEY_MAX_NSKEY)
goto bad_seckey;
pubkey_algo = map_pk_gcry_to_openpgp (pubkey_algo);
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "skey", 0);
@ -557,6 +558,77 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
goto leave;
}
/* We need to change the received parameters for ECC algorithms.
The transfer format has all parameters but OpenPGP defines that
only the OID of the curve is to be used. */
if (pubkey_algo == PUBKEY_ALGO_ECDSA || pubkey_algo == PUBKEY_ALGO_ECDH)
{
gcry_sexp_t s_pubkey;
const char *curvename, *curveoidstr;
gcry_mpi_t mpi;
/* We build an S-expression with the public key parameters and
ask Libgcrypt to return the matching curve name. */
if (npkey != 6 || !skey[0] || !skey[1] || !skey[2]
|| !skey[3] || !skey[4] || !skey[5]
|| !skey[6] || skey[7])
{
err = gpg_error (GPG_ERR_INTERNAL);
goto leave;
}
err = gcry_sexp_build (&s_pubkey, NULL,
"(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
skey[0], skey[1], skey[2], skey[3], skey[4]);
if (err)
goto leave;
#ifdef HAVE_GCRY_PK_GET_CURVE
curvename = gcry_pk_get_curve (s_pubkey, 0, NULL);
#else
curvename = "?";
#endif
gcry_sexp_release (s_pubkey);
curveoidstr = gpg_curve_to_oid (curvename, NULL);
if (!curveoidstr)
{
log_error ("no OID known for curve `%s'\n", curvename);
err = gpg_error (GPG_ERR_UNKNOWN_NAME);
goto leave;
}
err = openpgp_oid_from_str (curveoidstr, &mpi);
if (err)
goto leave;
/* Now replace the curve parameters by the OID and shift the
rest of the parameters. */
gcry_mpi_release (skey[0]);
skey[0] = mpi;
for (idx=1; idx <= 4; idx++)
gcry_mpi_release (skey[idx]);
skey[1] = skey[5];
skey[2] = skey[6];
for (idx=3; idx <= 6; idx++)
skey[idx] = NULL;
/* Fixup the NPKEY and NSKEY to match OpenPGP reality. */
npkey = 2;
nskey = 3;
/* for (idx=0; skey[idx]; idx++) */
/* { */
/* log_info ("YYY skey[%d]:", idx); */
/* if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
/* { */
/* void *p; */
/* unsigned int nbits; */
/* p = gcry_mpi_get_opaque (skey[idx], &nbits); */
/* log_printhex (NULL, p, (nbits+7)/8); */
/* } */
/* else */
/* gcry_mpi_dump (skey[idx]); */
/* log_printf ("\n"); */
/* } */
}
/* Do some sanity checks. */
if (s2k_count <= 1024)
{
@ -577,10 +649,16 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
if (err)
goto leave;
/* Check that the public key parameters match. */
/* Check that the public key parameters match. Since Libgcrypt 1.5
and the gcry_pk_get_curve function, gcry_mpi_cmp handles opaque
MPI correctly and thus we don't need to to do the extra
opaqueness checks. */
for (idx=0; idx < npkey; idx++)
if (gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
if (0
#ifndef HAVE_GCRY_PK_GET_CURVE
gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
|| gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)
#endif
|| gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
{
err = gpg_error (GPG_ERR_BAD_PUBKEY);

View File

@ -1959,6 +1959,9 @@ main (int argc, char **argv)
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
}
/* Use our own logging handler for Libcgrypt. */
setup_libgcrypt_logging ();
/* Put random number into secure memory */
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);

View File

@ -1,6 +1,6 @@
/* import.c - import a key into our key storage.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
* 2007, 2010 Free Software Foundation, Inc.
* 2007, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -1107,6 +1107,37 @@ import_one (ctrl_t ctrl,
}
/* Extract one MPI value from the S-expression PKEY which is expected
to hold a "public-key". Returns NULL on error. */
static gcry_mpi_t
one_mpi_from_pkey (gcry_sexp_t pkey, const char *name, size_t namelen)
{
gcry_sexp_t list, l2;
gcry_mpi_t a;
list = gcry_sexp_find_token (pkey, "public-key", 0);
if (!list)
return NULL;
l2 = gcry_sexp_cadr (list);
gcry_sexp_release (list);
list = l2;
if (!list)
return NULL;
l2 = gcry_sexp_find_token (list, name, namelen);
if (!l2)
{
gcry_sexp_release (list);
return NULL;
}
a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
gcry_sexp_release (list);
return a;
}
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
function prints diagnostics and returns an error code. */
static gpg_error_t
@ -1133,6 +1164,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
unsigned char *wrappedkey = NULL;
size_t wrappedkeylen;
char *cache_nonce = NULL;
gcry_mpi_t ecc_params[5] = {NULL, NULL, NULL, NULL, NULL};
/* Get the current KEK. */
err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@ -1148,7 +1180,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
if (!err)
err = gcry_cipher_setkey (cipherhd, kek, keklen);
if (err)
goto leave; xfree (kek);
goto leave;
xfree (kek);
kek = NULL;
main_pk = NULL;
@ -1161,6 +1194,20 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
if (!main_pk)
main_pk = pk;
/* Make sure the keyids are available. */
keyid_from_pk (pk, NULL);
if (node->pkt->pkttype == PKT_SECRET_KEY)
{
pk->main_keyid[0] = pk->keyid[0];
pk->main_keyid[1] = pk->keyid[1];
}
else
{
pk->main_keyid[0] = main_pk->keyid[0];
pk->main_keyid[1] = main_pk->keyid[1];
}
ski = pk->seckey_info;
if (!ski)
BUG ();
@ -1191,34 +1238,109 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
init_membuf (&mbuf, 50);
put_membuf_str (&mbuf, "(skey");
for (i=j=0; i < nskey; i++)
if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
if (!pk->pkey[i])
; /* Protected keys only have NPKEY+1 elements. */
else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{
put_membuf_str (&mbuf, " e %b");
format_args_buf_ptr[i] = gcry_mpi_get_opaque (pk->pkey[i], &n);
format_args_buf_int[i] = (n+7)/8;
format_args[j++] = format_args_buf_int + i;
format_args[j++] = format_args_buf_ptr + i;
}
/* We need special treatment for ECC algorithms. OpenPGP
stores only the curve name but the agent expects a full
key. This is so that we can keep all curve name
validation code out of gpg-agent. */
#if PUBKEY_MAX_NSKEY < 7
#error PUBKEY_MAX_NSKEY too low for ECC
#endif
char *curve = openpgp_oid_to_str (pk->pkey[0]);
if (!curve)
err = gpg_error_from_syserror ();
else
{
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = pk->pkey + i;
#ifdef HAVE_GCRY_PK_GET_CURVE /* Also ensures availability of get_param. */
gcry_sexp_t cparam = gcry_pk_get_param (GCRY_PK_ECDSA, curve);
#else
gcry_sexp_t cparam = NULL;
#endif
xfree (curve);
if (!cparam)
err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
else
{
const char *s;
/* Append the curve parameters P, A, B, G and N. */
for (i=j=0; !err && *(s = "pabgn"+i); i++)
{
ecc_params[i] = one_mpi_from_pkey (cparam, s, 1);
if (!ecc_params[i])
err = gpg_error (GPG_ERR_INV_CURVE);
else
{
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = ecc_params+i;
}
}
gcry_sexp_release (cparam);
if (!err)
{
/* Append the public key element Q. */
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = pk->pkey + 1;
/* Append the secret key element D. Note that
for ECDH we need to skip PKEY[2] because this
holds the KEK which is not needed. */
i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2;
if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{
put_membuf_str (&mbuf, " e %b");
format_args_buf_ptr[i]
= gcry_mpi_get_opaque (pk->pkey[i],&n);
format_args_buf_int[i] = (n+7)/8;
format_args[j++] = format_args_buf_int + i;
format_args[j++] = format_args_buf_ptr + i;
}
else
{
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = pk->pkey + i;
}
}
}
}
}
else
{
/* Standard case for the old (non-ECC) algorithms. */
for (i=j=0; i < nskey; i++)
{
if (!pk->pkey[i])
; /* Protected keys only have NPKEY+1 elements. */
else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{
put_membuf_str (&mbuf, " e %b");
format_args_buf_ptr[i] = gcry_mpi_get_opaque (pk->pkey[i],&n);
format_args_buf_int[i] = (n+7)/8;
format_args[j++] = format_args_buf_int + i;
format_args[j++] = format_args_buf_ptr + i;
}
else
{
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = pk->pkey + i;
}
}
}
put_membuf_str (&mbuf, ")\n");
put_membuf (&mbuf, "", 1);
{
char *format = get_membuf (&mbuf, NULL);
if (!format)
err = gpg_error_from_syserror ();
else
err = gcry_sexp_build_array (&skey, NULL, format, format_args);
xfree (format);
}
if (err)
xfree (get_membuf (&mbuf, NULL));
else
{
char *format = get_membuf (&mbuf, NULL);
if (!format)
err = gpg_error_from_syserror ();
else
err = gcry_sexp_build_array (&skey, NULL, format, format_args);
xfree (format);
}
if (err)
{
log_error ("error building skey array: %s\n", gpg_strerror (err));
@ -1328,6 +1450,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
}
leave:
for (i=0; i < DIM (ecc_params); i++)
gcry_mpi_release (ecc_params[i]);
xfree (cache_nonce);
xfree (wrappedkey);
xfree (transferkey);

View File

@ -1080,6 +1080,40 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
return err;
}
/* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL
store the bit size of the curve there. Returns NULL for unknown
curve names. */
const char *
gpg_curve_to_oid (const char *name, unsigned int *r_nbits)
{
unsigned int nbits = 0;
const char *oidstr;
if (!name)
oidstr = NULL;
else if (!strcmp (name, "NIST P-256"))
{
oidstr = "1.2.840.10045.3.1.7";
nbits = 256;
}
else if (!strcmp (name, "NIST P-384"))
{
oidstr = "1.3.132.0.34";
nbits = 384;
}
else if (!strcmp (name, "NIST P-521"))
{
oidstr = "1.3.132.0.35";
nbits = 521;
}
else
oidstr = NULL;
if (r_nbits)
*r_nbits = nbits;
return oidstr;
}
static gpg_error_t
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
@ -1117,23 +1151,11 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
goto leave;
}
gcry_sexp_release (l2);
if (!strcmp (curve, "NIST P-256"))
{
oidstr = "1.2.840.10045.3.1.7";
nbits = 256;
}
else if (!strcmp (curve, "NIST P-384"))
{
oidstr = "1.3.132.0.34";
nbits = 384;
}
else if (!strcmp (curve, "NIST P-521"))
{
oidstr = "1.3.132.0.35";
nbits = 521;
}
else
oidstr = gpg_curve_to_oid (curve, &nbits);
if (!oidstr)
{
/* That can't happen because we used one of the curves
gpg_curve_to_oid knows about. */
err = gpg_error (GPG_ERR_INV_OBJ);
goto leave;
}
@ -1445,7 +1467,8 @@ gen_ecc (int algo, unsigned int nbits, kbnode_t pub_root,
assert (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH);
/* For now we may only use one of the 3 NISY curves. */
/* For now we may only use one of the 3 NIST curves. See also
gpg_curve_to_oid. */
if (nbits <= 256)
curve = "NIST P-256";
else if (nbits <= 384)

View File

@ -81,6 +81,11 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
if(pk->version<4)
n+=2;
/* FIXME: We can avoid the extra malloc by calling only the first
mpi_print here which computes the required length and calling the
real mpi_print only at the end. The speed advantage would only be
for ECC (opaque MPIs) or if we could implement an mpi_print
variant with a callback handler to do the hashing. */
if (npkey==0 && pk->pkey[0]
&& gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
{
@ -92,22 +97,29 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
{
for (i=0; i < npkey; i++ )
{
enum gcry_mpi_format fmt;
if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{
size_t nbits;
const void *p;
if ((pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
&& (i == 0 || i == 2))
fmt = GCRYMPI_FMT_USG; /* Name of OID or KEK parms. */
p = gcry_mpi_get_opaque (pk->pkey[i], &nbits);
pp[i] = xmalloc ((nbits+7)/8);
memcpy (pp[i], p, (nbits+7)/8);
nn[i] = (nbits+7)/8;
n += nn[i];
}
else
fmt = GCRYMPI_FMT_PGP;
if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i]))
BUG ();
pp[i] = xmalloc (nbytes);
if (gcry_mpi_print (fmt, pp[i], nbytes, &nbytes, pk->pkey[i]))
BUG ();
nn[i] = nbytes;
n += nn[i];
{
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0,
&nbytes, pk->pkey[i]))
BUG ();
pp[i] = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
&nbytes, pk->pkey[i]))
BUG ();
nn[i] = nbytes;
n += nn[i];
}
}
}
@ -786,4 +798,3 @@ hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
}
return err;
}

View File

@ -236,6 +236,7 @@ void keyedit_passwd (ctrl_t ctrl, const char *username);
void show_basic_key_info (KBNODE keyblock);
/*-- keygen.c --*/
const char *gpg_curve_to_oid (const char *name, unsigned int *r_nbits);
u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);

View File

@ -1,3 +1,8 @@
2011-02-01 Werner Koch <wk@g10code.com>
* cipher.h (PUBKEY_MAX_NPKEY, PUBKEY_MAX_NSKEY): Bump up to
accommodate gcrypt ECC keys.
2011-01-21 Werner Koch <wk@g10code.com>
* cipher.h (GCRY_PK_USAGE_CERT): Remove compatibility macros

View File

@ -100,8 +100,8 @@ typedef struct
/* Constants to allocate static MPI arrays. */
#define PUBKEY_MAX_NPKEY 4
#define PUBKEY_MAX_NSKEY 6
#define PUBKEY_MAX_NPKEY 5
#define PUBKEY_MAX_NSKEY 7
#define PUBKEY_MAX_NSIG 2
#define PUBKEY_MAX_NENC 2

View File

@ -1,4 +1,5 @@
no-creation-time.gpg A key with a zero creation time.
ecc-sample-1-pub.asc The first ECC sample key.
ecc-sample-1-sec.asc The first ECC sample key (secret).

View File

@ -0,0 +1,22 @@
The key has been generated by the first GnuPG ECC version at
http://code.google.com/p/gnupg-ecc.
The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
with KDF.
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.1.0-ecc (GNU/Linux)
mFIETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLmtCRlY19kc2FfZGhf
MjU2IDxvcGVucGdwQGJyYWluaHViLm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgH
AwIGFQgCCQoLBBYCAwECHgECF4AACgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9d
JtLJ5As98Alit2oFwzhxG7mSVmQA/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehx
XDfpHj+/uFYETJPQrRIIKoZIzj0DAQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1X
XsRJEwrzftreZYrn7jXSDoiXkRyfVkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB4hh
BBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYBAOSUmaQ8rkgihnepbnpK7tNz
3QEocsLEtsTCDUBGNYGyAQDclifYqsUChXlWKaw3md+yHJPcWZXzHt37c4q/MhIm
oQ==
=hMzp
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,25 @@
The key has been generated by the first GnuPG ECC version at
http://code.google.com/p/gnupg-ecc.
The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
with KDF. The password for the key is "ecc".
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2.1.0-ecc (GNU/Linux)
lJ0ETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLm/gMDAmHomSLb9NbE
oyWUoqgKTbZzbFR/SWmiCcuiQEhREcTyvyU1hAglj7FsBJoQ6/pbeAEQZ3bVzlNM
8F0nF8KPLPuEADF1+4CntCRlY19kc2FfZGhfMjU2IDxvcGVucGdwQGJyYWluaHVi
Lm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
CgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9dJtLJ5As98Alit2oFwzhxG7mSVmQA
/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehxXDfpHj+/nKEETJPQrRIIKoZIzj0D
AQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1XXsRJEwrzftreZYrn7jXSDoiXkRyf
VkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB/4DAwJh6Jki2/TWxKO7gHKWIcOcxYZp
CRWjlUghbKb6Q83p8GLPjKRN0USl/U1tObWdksqMXhUO0ePLWUnrbwoWYfYXg9Er
ADTgCYhhBBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYA/3eJRirPQZmBno+Z
P/HOBSFWmFt4cUBGUx3oqiUd5loOAP480pb+vXx9ipljJWCJDSl/boRSuqB4hePP
qt9Rd5gNdQ==
=O8Dg
-----END PGP PRIVATE KEY BLOCK-----