summaryrefslogtreecommitdiffstats
path: root/g10/ecdh.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-01-31 15:44:24 +0100
committerWerner Koch <wk@gnupg.org>2011-01-31 15:44:24 +0100
commit328a642aa5ed971870a2667b06307f760fa251dc (patch)
tree04fc123c7eedea823eeaeefaf56f19ce7598d2bd /g10/ecdh.c
parentReworked the ECC changes to better fit into the Libgcrypt API. (diff)
downloadgnupg2-328a642aa5ed971870a2667b06307f760fa251dc.tar.xz
gnupg2-328a642aa5ed971870a2667b06307f760fa251dc.zip
Fixed the ECC interface to Libgcrypt to be ABI compatible with the previous version.
Quite some changes were needed but in the end we have less code than before. Instead of trying to do everything with MPIs and pass them back and forth between Libgcrypt and GnuPG, we know use the S-expression based interface and make heavy use of our opaque MPI feature. Encryption, decryption, signing and verification work with self-generared keys. Import and export does not yet work; thus it was not possible to check the test keys at https://sites.google.com/site/brainhub/pgpecckeys .
Diffstat (limited to 'g10/ecdh.c')
-rw-r--r--g10/ecdh.c191
1 files changed, 97 insertions, 94 deletions
diff --git a/g10/ecdh.c b/g10/ecdh.c
index cf002b957..09ab3ed16 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -1,5 +1,5 @@
/* ecdh.c - ECDH public key operations used in public key glue code
- * Copyright (C) 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -105,11 +105,13 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
gpg_error_t err;
byte *secret_x;
int secret_x_size;
- byte kdf_params[256];
- int kdf_params_size=0;
- int nbits;
+ unsigned int nbits;
+ const unsigned char *kdf_params;
+ size_t kdf_params_size;
int kdf_hash_algo;
int kdf_encr_algo;
+ unsigned char message[256];
+ size_t message_size;
*r_result = NULL;
@@ -137,12 +139,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
return err;
}
- /* fixme: explain what we are doing. */
secret_x_size = (nbits+7)/8;
assert (nbytes > secret_x_size);
memmove (secret_x, secret_x+1, secret_x_size);
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
-
+
if (DBG_CIPHER)
log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
}
@@ -155,38 +156,34 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
* current secret_x with a value derived from it. This will become
* a KEK.
*/
- {
- IOBUF obuf = iobuf_temp();
- err = write_size_body_mpi (obuf, pkey[2]); /* KEK params */
-
- kdf_params_size = iobuf_temp_to_buffer (obuf,
- kdf_params, sizeof(kdf_params));
-
- if (DBG_CIPHER)
- log_printhex ("ecdh KDF public key params are:",
- kdf_params, kdf_params_size );
-
- /* Expect 4 bytes 03 01 hash_alg symm_alg. */
- if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1)
- return GPG_ERR_BAD_PUBKEY;
-
- kdf_hash_algo = kdf_params[2];
- kdf_encr_algo = kdf_params[3];
-
- if (DBG_CIPHER)
- log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
- gcry_md_algo_name (kdf_hash_algo),
- openpgp_cipher_algo_name (kdf_encr_algo));
-
- if (kdf_hash_algo != GCRY_MD_SHA256
- && kdf_hash_algo != GCRY_MD_SHA384
- && kdf_hash_algo != GCRY_MD_SHA512)
- return GPG_ERR_BAD_PUBKEY;
- if (kdf_encr_algo != GCRY_CIPHER_AES128
- && kdf_encr_algo != GCRY_CIPHER_AES192
- && kdf_encr_algo != GCRY_CIPHER_AES256)
- return GPG_ERR_BAD_PUBKEY;
- }
+ 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;
+
+ if (DBG_CIPHER)
+ log_printhex ("ecdh KDF params:", kdf_params, kdf_params_size);
+
+ /* Expect 4 bytes 03 01 hash_alg symm_alg. */
+ if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1)
+ return GPG_ERR_BAD_PUBKEY;
+
+ kdf_hash_algo = kdf_params[2];
+ kdf_encr_algo = kdf_params[3];
+
+ if (DBG_CIPHER)
+ log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
+ openpgp_md_algo_name (kdf_hash_algo),
+ openpgp_cipher_algo_name (kdf_encr_algo));
+
+ if (kdf_hash_algo != GCRY_MD_SHA256
+ && kdf_hash_algo != GCRY_MD_SHA384
+ && kdf_hash_algo != GCRY_MD_SHA512)
+ return GPG_ERR_BAD_PUBKEY;
+ if (kdf_encr_algo != GCRY_CIPHER_AES128
+ && kdf_encr_algo != GCRY_CIPHER_AES192
+ && kdf_encr_algo != GCRY_CIPHER_AES256)
+ return GPG_ERR_BAD_PUBKEY;
/* Build kdf_params. */
{
@@ -194,18 +191,17 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
obuf = iobuf_temp();
/* variable-length field 1, curve name OID */
- err = write_size_body_mpi (obuf, pkey[0]);
+ err = gpg_mpi_write (obuf, pkey[0]);
/* fixed-length field 2 */
iobuf_put (obuf, PUBKEY_ALGO_ECDH);
/* variable-length field 3, KDF params */
- err = (err ? err : write_size_body_mpi ( obuf, pkey[2] ));
+ err = (err ? err : gpg_mpi_write (obuf, pkey[2]));
/* fixed-length field 4 */
iobuf_write (obuf, "Anonymous Sender ", 20);
/* fixed-length field 5, recipient fp */
iobuf_write (obuf, pk_fp, 20);
- kdf_params_size = iobuf_temp_to_buffer (obuf,
- kdf_params, sizeof(kdf_params));
+ message_size = iobuf_temp_to_buffer (obuf, message, sizeof message);
iobuf_close (obuf);
if (err)
return err;
@@ -223,10 +219,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
err = gcry_md_open (&h, kdf_hash_algo, 0);
if(err)
log_bug ("gcry_md_open failed for algo %d: %s",
- kdf_hash_algo, gpg_strerror (gcry_error(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 */
+ 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_final (h);
@@ -320,13 +316,13 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
if (DBG_CIPHER)
log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
- err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
- data_buf, 1+data_buf[0], NULL);
- /* (byte)size + aeswrap of DEK */
- xfree( data_buf );
- if (err)
+ result = gcry_mpi_set_opaque (NULL, data_buf, 8 * (1+data_buf[0]));
+ if (!result)
{
- log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (err));
+ err = gpg_error_from_syserror ();
+ xfree (data_buf);
+ log_error ("ecdh failed to create an MPI: %s\n",
+ gpg_strerror (err));
return err;
}
@@ -335,55 +331,62 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
else
{
byte *in;
+ const void *p;
- err = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size,
- &nbytes, data/*in*/);
- if (nbytes != data_buf_size || data_buf[0] != data_buf_size-1)
+ p = gcry_mpi_get_opaque (data, &nbits);
+ nbytes = (nbits+7)/8;
+ if (!p || nbytes > data_buf_size || !nbytes)
+ {
+ xfree (data_buf);
+ return GPG_ERR_BAD_MPI;
+ }
+ memcpy (data_buf, p, nbytes);
+ if (data_buf[0] != nbytes-1)
{
log_error ("ecdh inconsistent size\n");
xfree (data_buf);
return GPG_ERR_BAD_MPI;
}
- in = data_buf+data_buf_size;
- data_buf_size = data_buf[0];
-
- if (DBG_CIPHER)
- log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
-
- err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
- data_buf_size);
- gcry_cipher_close (hd);
- if (err)
- {
- log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
- gpg_strerror (err));
- xfree (data_buf);
- return err;
- }
-
- data_buf_size -= 8;
-
- if (DBG_CIPHER)
- log_printhex ("ecdh decrypted to :", in, data_buf_size);
-
- /* Padding is removed later. */
- /* if (in[data_buf_size-1] > 8 ) */
- /* { */
- /* log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", */
- /* in[data_buf_size-1] ); */
- /* return GPG_ERR_BAD_KEY; */
- /* } */
+ in = data_buf+data_buf_size;
+ data_buf_size = data_buf[0];
+
+ if (DBG_CIPHER)
+ log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
+
+ err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
+ data_buf_size);
+ gcry_cipher_close (hd);
+ if (err)
+ {
+ log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
+ gpg_strerror (err));
+ xfree (data_buf);
+ return err;
+ }
+
+ data_buf_size -= 8;
+
+ if (DBG_CIPHER)
+ log_printhex ("ecdh decrypted to :", in, data_buf_size);
+
+ /* Padding is removed later. */
+ /* if (in[data_buf_size-1] > 8 ) */
+ /* { */
+ /* log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", */
+ /* in[data_buf_size-1] ); */
+ /* return GPG_ERR_BAD_KEY; */
+ /* } */
- err = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
- xfree (data_buf);
- if (err)
- {
- log_error ("ecdh failed to create a plain text MPI: %s\n",
- gpg_strerror (err));
- return err;
- }
-
- *r_result = result;
+ err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
+ xfree (data_buf);
+ if (err)
+ {
+ log_error ("ecdh failed to create a plain text MPI: %s\n",
+ gpg_strerror (err));
+ return err;
+ }
+
+ *r_result = result;
}
}