[git] GCRYPT - branch, ECC-INTEGRATION-1-5, updated. libgcrypt-1.4.4-51-g8993868
by Andrey Jivsov
cvs at cvs.gnupg.org
Tue Jan 11 05:31:35 CET 2011
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".
The branch, ECC-INTEGRATION-1-5 has been updated
via 899386826c85f1e757e75bcc5d5b2159d05676a0 (commit)
from 2c32b631acc1637c1d7826bcdcecf6c0ae9ce7fc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 899386826c85f1e757e75bcc5d5b2159d05676a0
Author: Andrey Jivsov <openpgp at brainhub.org>
Date: Mon Jan 10 20:11:54 2011 -0800
'g10/gpg2 --encrypt --debug 15 -r ecdsa -a -o _e.asc _' and 'g10/gpg2 --debug 15 _e.asc', as well as decoding of an old message posted on https://sites.google.com/site/brainhub/pgpecckeys work.
This is the milestone 2 that brings in ECDH support from http://code.google.com/p/gnupg-ecc/source/detail?r=15 .
Updated the ECDH code to work with latest gnupg that doesn't expose private components of a public key.
diff --git a/cipher/ecc.c b/cipher/ecc.c
index fdcbb4c..f33cc1c 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1337,36 +1337,61 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
}
-/* ecdh is very simple. It is basically the implementation of the primitive operation in the EC field.
- * 'data' is scalar, 2-MPI array pkey uniquely defines a point on the curve.
+/* ecdh raw is classic 2-round DH protocol published in 1976.
+ * Some overloading is needed to fit it to encrypt/decrypt PK interface of libgcrypt.
+ *
+ * The only need for this complexity is that some designs of client of libgcrypt
+ * don't allow to get the private components of public keys.
*
- * The complexity of ECDH encryption is shifted into OpenPGP layer to keep libgcrypt
- * layer generic. ecc_encrypt is identical to ecc_decrypt due to the symmetry of DH protocol.
+ * Overview of ecc_encrypt_raw and ecc_decrypt_raw.
+ *
+ * As with any PK operation, encrypt version uses a public key and decrypt -- private.
+ *
+ * Symbols used bellow:
+ * G - field generator point
+ * x - private long-term scalar
+ * xG - public long-term key
+ * k - ephemeral scalar
+ * kG - ephemeral public key
+ * xkG - shared secret
+ *
+ * ecc_encrypt_raw description:
+ * input:
+ * data[0] : private scalar (k)
+ * output:
+ * resaddr[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret)
+ * resaddr[1] : generated ephemeral public key (kG)
+ *
+ * ecc_decrypt_raw description:
+ * input:
+ * data[0] : a point kG (ephemeral public key)
+ * output:
+ * result[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret)
*/
static gcry_err_code_t
-ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
+ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
{
ECC_secret_key sk;
- mpi_point_t R; /* result that we return */
mpi_ec_t ctx;
- gcry_mpi_t result;
+ gcry_mpi_t result[2];
+ mpi_point_t eph_Q;
int err;
(void)algo;
(void)flags;
if (DBG_CIPHER)
- log_debug ("Called ecc_encrypt data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags);
+ log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags);
if ( !data || !pkey[0] || !pkey[1] )
return GPG_ERR_BAD_MPI;
if (DBG_CIPHER)
{
- log_mpidump ("ecdh encrypt c ", pkey[0]);
- log_mpidump ("ecdh encrypt q ", pkey[1]);
- log_mpidump ("ecdh encrypt p ", pkey[2]);
- log_mpidump ("ecdh encrypt data", data);
+ log_mpidump ("ecdh encrypt PK c ", pkey[0]);
+ log_mpidump ("ecdh encrypt PK q ", pkey[1]);
+ log_mpidump ("ecdh encrypt PK p ", pkey[2]);
+ log_mpidump ("ecdh encrypt data k", data);
}
if( (err=mpi_to_name_oid( pkey[0], sk.E.name_oid )) )
@@ -1385,6 +1410,108 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in
ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a);
+
+ /* the following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
+ {
+ mpi_point_t R; /* result that we return */
+ gcry_mpi_t x,y;
+
+ x = mpi_new (0);
+ y = mpi_new (0);
+
+ point_init (&R);
+
+ _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx);
+
+ if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
+ log_fatal ("ecdh: Failed to get affine coordinates for xkG\n");
+
+ result[0] = ec2os( x, y, sk.E.p ); /* xkG */
+
+ _gcry_mpi_ec_mul_point (&R, sk.d, &sk.E.G, ctx);
+
+ if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
+ log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
+
+ result[1] = ec2os( x, y, sk.E.p ); /* kG */
+
+ mpi_free(x);
+ mpi_free(y);
+
+ point_free( &R );
+ }
+
+ _gcry_mpi_ec_free (ctx);
+ ecc_sk_free( &sk );
+
+ if( result[0] == NULL || result[1] == NULL ) {
+ mpi_free( result[0] );
+ mpi_free( result[1] );
+ return GPG_ERR_ENOMEM;
+ }
+
+ /* success */
+
+ /* none of 2 returned values are used as is; they are further processed at OpenPGP layer.
+ * However, they match the number of MPIs (2) needed to encrypt a message in OpenPGP format
+ */
+ resarr[0] = result[0];
+ resarr[1] = result[1];
+
+ return GPG_ERR_NO_ERROR;
+}
+
+ /* input:
+ * data[0] : a point kG (ephemeral public key)
+ * output:
+ * resaddr[0] : shared point k*x*G
+ *
+ * see ecc_encrypt_raw for details.
+ */
+static gcry_err_code_t
+ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
+{
+ ECC_secret_key sk;
+ mpi_point_t R; /* result that we return */
+ mpi_ec_t ctx;
+ gcry_mpi_t r;
+ int err;
+
+ (void)algo;
+ (void)flags;
+
+ *result = NULL;
+
+ if (DBG_CIPHER)
+ log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags);
+
+ if ( !data || !data[0] || !skey[0] || !skey[1] || !skey[3] )
+ return GPG_ERR_BAD_MPI;
+
+ if (DBG_CIPHER)
+ {
+ log_mpidump ("ecdh decrypt SK c ", skey[0]);
+ log_mpidump ("ecdh decrypt SK q ", skey[1]);
+ log_mpidump ("ecdh decrypt SK p ", skey[2]);
+ log_mpidump ("ecdh decrypt data kG", data[0]);
+ }
+
+ if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) )
+ return err;
+ if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) )
+ return err;
+
+ point_init (&sk.Q);
+ err = os2ec (&sk.Q, data[0]);
+ sk.d = gcry_mpi_copy( skey[3] );
+ if (err)
+ {
+ ecc_sk_free( &sk );
+ return err;
+ }
+
+ ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a);
+
point_init (&R);
_gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx);
@@ -1397,7 +1524,7 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in
if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
log_fatal ("ecdh: Failed to get affine coordinates\n");
- result = ec2os( x, y, sk.E.p );
+ r = ec2os( x, y, sk.E.p );
mpi_free(x);
mpi_free(y);
}
@@ -1406,23 +1533,16 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in
_gcry_mpi_ec_free (ctx);
ecc_sk_free( &sk );
- if( result == NULL )
+ if( r == NULL )
return GPG_ERR_ENOMEM;
/* success */
- resarr[0] = result;
- resarr[1] = mpi_new (0); /* not used; it is constructruced at OpenPGP layer */
+ *result = r;
return GPG_ERR_NO_ERROR;
}
-static gcry_err_code_t
-ecc_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
-{
- return ecc_encrypt( algo, result, data[0], skey, flags );
-}
-
static unsigned int
ecc_get_nbits (int algo, gcry_mpi_t *pkey)
{
@@ -1625,8 +1745,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdh =
GCRY_PK_USAGE_ENCR,
ecc_generate,
ecc_check_secret_key,
- ecc_encrypt,
- ecc_decrypt,
+ ecc_encrypt_raw,
+ ecc_decrypt_raw,
NULL,
NULL,
ecc_get_nbits
-----------------------------------------------------------------------
Summary of changes:
cipher/ecc.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 144 insertions(+), 24 deletions(-)
hooks/post-receive
--
The GNU crypto library
http://git.gnupg.org
More information about the Gnupg-commits
mailing list