summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-02-02 17:40:32 +0100
committerWerner Koch <wk@gnupg.org>2011-02-02 17:40:32 +0100
commit20f429f735d6e965e0660484f8286fe24fb6162b (patch)
tree8908aa1b86c2be5a83ca4e1883da86234b931a3b
parentSample ECC keys and message do now work. (diff)
downloadgnupg2-20f429f735d6e965e0660484f8286fe24fb6162b.tar.xz
gnupg2-20f429f735d6e965e0660484f8286fe24fb6162b.zip
Compute the fingerprint for ECDH only on demand.
This also fixes a failed assertion when using a v3 key where the fingerprint size is not 20.
-rw-r--r--g10/ChangeLog6
-rw-r--r--g10/encrypt.c129
-rw-r--r--g10/pkglue.c27
-rw-r--r--g10/pkglue.h7
4 files changed, 90 insertions, 79 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index bb55ff85f..b3358c9d9 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,11 @@
2011-02-02 Werner Koch <wk@g10code.com>
+ * encrypt.c (write_pubkey_enc_from_list): Don't compute the
+ fingerprint.
+ * pkglue.c (pk_encrypt): Replace PK_FP by PK and compute the
+ fingerprint only when needed.
+ * pkglue.h: Include packet.h.
+
* import.c (transfer_secret_keys): Make sure keyids are available.
* keyid.c (hash_public_key): Adjust for the ECC case.
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 8548a5739..83b43a89e 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -84,7 +84,7 @@ encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey)
/* The encrypted session key is prefixed with a one-octet algorithm id. */
buf[0] = (*seskey)->algo;
memcpy( buf + 1, (*seskey)->key, (*seskey)->keylen );
-
+
/* We only pass already checked values to the following fucntion,
thus we consider any failure as fatal. */
if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
@@ -119,7 +119,7 @@ use_mdc(PK_LIST pk_list,int algo)
if(select_mdc_from_pklist(pk_list))
return 1;
-
+
/* The keys don't support MDC, so now we do a bit of a hack - if any
of the AESes or TWOFISH are in the prefs, we assume that the user
can handle a MDC. This is valid for PGP 7, which can handle MDCs
@@ -181,7 +181,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx);
init_packet(&pkt);
-
+
/* Prepare iobufs. */
inp = iobuf_open(filename);
if (inp)
@@ -200,23 +200,23 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
release_progress_context (pfx);
return rc;
}
-
+
handle_progress (pfx, inp, filename);
-
+
if (opt.textmode)
iobuf_push_filter( inp, text_filter, &tfx );
-
+
/* Due the the fact that we use don't use an IV to encrypt the
session key we can't use the new mode with RFC1991 because it has
no S2K salt. RFC1991 always uses simple S2K. */
if ( RFC1991 && use_seskey )
use_seskey = 0;
-
+
cfx.dek = NULL;
- if ( mode )
+ if ( mode )
{
int canceled;
-
+
s2k = xmalloc_clear( sizeof *s2k );
s2k->mode = RFC1991? 0:opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO;
@@ -233,37 +233,37 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
release_progress_context (pfx);
return rc;
}
- if (use_seskey && s2k->mode != 1 && s2k->mode != 3)
+ if (use_seskey && s2k->mode != 1 && s2k->mode != 3)
{
use_seskey = 0;
log_info (_("can't use a symmetric ESK packet "
"due to the S2K mode\n"));
}
-
+
if ( use_seskey )
{
DEK *dek = NULL;
-
+
seskeylen = openpgp_cipher_get_algo_keylen (default_cipher_algo ());
encrypt_seskey( cfx.dek, &dek, enckey );
xfree( cfx.dek ); cfx.dek = dek;
}
-
+
if (opt.verbose)
log_info(_("using cipher %s\n"),
openpgp_cipher_algo_name (cfx.dek->algo));
-
+
cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
}
-
+
if (do_compress && cfx.dek && cfx.dek->use_mdc
&& is_file_compressed(filename, &rc))
{
if (opt.verbose)
log_info(_("`%s' already compressed\n"), filename);
- do_compress = 0;
+ do_compress = 0;
}
-
+
if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, &out )))
{
iobuf_cancel (inp);
@@ -272,7 +272,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
release_progress_context (pfx);
return rc;
}
-
+
if ( opt.armor )
{
afx = new_armor_context ();
@@ -296,7 +296,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
xfree (enc);
}
-
+
if (!opt.no_literal)
pt = setup_plaintext_name (filename, inp);
@@ -347,7 +347,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
pkt.pkttype = 0;
pkt.pkt.generic = NULL;
}
-
+
/* Register the cipher filter. */
if (mode)
iobuf_push_filter ( out, cipher_filter, &cfx );
@@ -359,14 +359,14 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
zfx.new_ctb = 1;
push_compress_filter (out, &zfx, default_compress_algo());
}
-
+
/* Do the work. */
if (!opt.no_literal)
{
if ( (rc = build_packet( out, &pkt )) )
log_error("build_packet failed: %s\n", g10_errstr(rc) );
}
- else
+ else
{
/* User requested not to create a literal packet, so we copy the
plain data. */
@@ -380,12 +380,12 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
}
wipememory (copy_buffer, 4096); /* burn buffer */
}
-
+
/* Finish the stuff. */
iobuf_close (inp);
if (rc)
iobuf_cancel(out);
- else
+ else
{
iobuf_close (out); /* fixme: check returncode */
if (mode)
@@ -425,7 +425,7 @@ setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek)
static int
-write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
+write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
iobuf_t out)
{
int rc, seskeylen = openpgp_cipher_get_algo_keylen (dek->algo);
@@ -492,7 +492,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
memset( &tfx, 0, sizeof tfx);
init_packet(&pkt);
- if (use_symkey
+ if (use_symkey
&& (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
{
release_progress_context (pfx);
@@ -509,7 +509,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
return rc;
}
}
-
+
if(PGP2)
{
for (work_list=pk_list; work_list; work_list=work_list->next)
@@ -560,17 +560,17 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
rc = open_outfile (outputfd, filename, opt.armor? 1:0, &out);
if (rc)
goto leave;
-
+
if (opt.armor)
{
afx = new_armor_context ();
push_armor_filter (afx, out);
}
-
+
/* Create a session key. */
cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
if (!opt.def_cipher_algo)
- {
+ {
/* Try to get it from the prefs. */
cfx.dek->algo = select_algo_from_prefs (pk_list, PREFTYPE_SYM, -1, NULL);
/* The only way select_algo_from_prefs can fail here is when
@@ -582,7 +582,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
if (cfx.dek->algo == -1)
{
cfx.dek->algo = CIPHER_ALGO_3DES;
-
+
if (PGP2)
{
log_info(_("unable to use the IDEA cipher for all of the keys "
@@ -610,12 +610,12 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
openpgp_cipher_algo_name (opt.def_cipher_algo),
opt.def_cipher_algo);
}
-
+
cfx.dek->algo = opt.def_cipher_algo;
}
-
+
cfx.dek->use_mdc = use_mdc (pk_list,cfx.dek->algo);
-
+
/* Only do the is-file-already-compressed check if we are using a
MDC. This forces compressed files to be re-compressed if we do
not have a MDC to give some protection against chosen ciphertext
@@ -625,7 +625,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
{
if (opt.verbose)
log_info(_("`%s' already compressed\n"), filename);
- do_compress = 0;
+ do_compress = 0;
}
if (rc2)
{
@@ -636,7 +636,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
make_session_key (cfx.dek);
if (DBG_CIPHER)
log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen );
-
+
rc = write_pubkey_enc_from_list (pk_list, cfx.dek, out);
if (rc)
goto leave;
@@ -647,16 +647,16 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
secret key needed to decrypt. */
if(use_symkey && (rc = write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
goto leave;
-
+
if (!opt.no_literal)
pt = setup_plaintext_name (filename, inp);
-
+
if (filefd != -1
&& !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
{
off_t tmpsize;
int overflow;
-
+
if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
&& !overflow && opt.verbose)
log_info(_("WARNING: `%s' is an empty file\n"), filename );
@@ -672,7 +672,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
else
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
- if (!opt.no_literal)
+ if (!opt.no_literal)
{
pt->timestamp = make_timestamp();
pt->mode = opt.textmode ? 't' : 'b';
@@ -693,7 +693,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
if (do_compress)
{
int compr_algo = opt.compress_algo;
-
+
if (compr_algo == -1)
{
compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL);
@@ -702,7 +702,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
/* Theoretically impossible to get here since uncompressed
is implicit. */
}
- else if (!opt.expert
+ else if (!opt.expert
&& select_algo_from_prefs(pk_list, PREFTYPE_ZIP,
compr_algo, NULL) != compr_algo)
{
@@ -710,7 +710,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
" violates recipient preferences\n"),
compress_algo_to_string(compr_algo), compr_algo);
}
-
+
/* Algo 0 means no compression. */
if (compr_algo)
{
@@ -719,7 +719,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
push_compress_filter (out,&zfx,compr_algo);
}
}
-
+
/* Do the work. */
if (!opt.no_literal)
{
@@ -750,7 +750,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
iobuf_close (inp);
if (rc)
iobuf_cancel (out);
- else
+ else
{
iobuf_close (out); /* fixme: check returncode */
write_status (STATUS_END_ENCRYPTION);
@@ -779,7 +779,7 @@ encrypt_filter (void *opaque, int control,
size_t size = *ret_len;
encrypt_filter_context_t *efx = opaque;
int rc = 0;
-
+
if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */
{
BUG(); /* not used */
@@ -789,19 +789,19 @@ encrypt_filter (void *opaque, int control,
if ( !efx->header_okay )
{
efx->cfx.dek = xmalloc_secure_clear ( sizeof *efx->cfx.dek );
- if ( !opt.def_cipher_algo )
+ if ( !opt.def_cipher_algo )
{
/* Try to get it from the prefs. */
efx->cfx.dek->algo =
select_algo_from_prefs (efx->pk_list, PREFTYPE_SYM, -1, NULL);
- if (efx->cfx.dek->algo == -1 )
+ if (efx->cfx.dek->algo == -1 )
{
/* Because 3DES is implicitly in the prefs, this can
only happen if we do not have any public keys in
the list. */
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
}
-
+
/* In case 3DES has been selected, print a warning if
any key does not have a preference for AES. This
should help to indentify why encrypting to several
@@ -810,7 +810,7 @@ encrypt_filter (void *opaque, int control,
&& efx->cfx.dek->algo == CIPHER_ALGO_3DES)
warn_missing_aes_from_pklist (efx->pk_list);
}
- else
+ else
{
if (!opt.expert
&& select_algo_from_prefs (efx->pk_list,PREFTYPE_SYM,
@@ -820,12 +820,12 @@ encrypt_filter (void *opaque, int control,
"violates recipient preferences\n"),
openpgp_cipher_algo_name (opt.def_cipher_algo),
opt.def_cipher_algo);
-
+
efx->cfx.dek->algo = opt.def_cipher_algo;
}
-
+
efx->cfx.dek->use_mdc = use_mdc (efx->pk_list,efx->cfx.dek->algo);
-
+
make_session_key ( efx->cfx.dek );
if (DBG_CIPHER)
log_printhex ("DEK is: ", efx->cfx.dek->key, efx->cfx.dek->keylen);
@@ -841,13 +841,13 @@ encrypt_filter (void *opaque, int control,
if(rc)
return rc;
}
-
+
iobuf_push_filter (a, cipher_filter, &efx->cfx);
-
+
efx->header_okay = 1;
}
rc = iobuf_write (a, buf, size);
-
+
}
else if (control == IOBUFCTRL_FREE)
{
@@ -876,11 +876,9 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
for ( ; pk_list; pk_list = pk_list->next )
{
gcry_mpi_t frame;
- byte fp[MAX_FINGERPRINT_LEN];
- size_t fpn;
pk = pk_list->pk;
-
+
print_pubkey_algo_note ( pk->pubkey_algo );
enc = xmalloc_clear ( sizeof *enc );
enc->pubkey_algo = pk->pubkey_algo;
@@ -894,9 +892,6 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
compliance_failure();
}
- fingerprint_from_pk (pk, fp, &fpn);
- assert (fpn == 20);
-
/* Okay, what's going on: We have the session key somewhere in
* the structure DEK and want to encode this session key in an
* integer value of n bits. pubkey_nbits gives us the number of
@@ -909,9 +904,9 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
* for Elgamal). We don't need frame anymore because we have
* everything now in enc->data which is the passed to
* build_packet(). */
- frame = encode_session_key (pk->pubkey_algo, dek,
+ frame = encode_session_key (pk->pubkey_algo, dek,
pubkey_nbits (pk->pubkey_algo, pk->pkey));
- rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, fp, pk->pkey);
+ rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk, pk->pkey);
gcry_mpi_release (frame);
if (rc)
log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
@@ -932,7 +927,7 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
pkt.pkt.pubkey_enc = enc;
rc = build_packet (out, &pkt);
if (rc)
- log_error ("build_packet(pubkey_enc) failed: %s\n",
+ log_error ("build_packet(pubkey_enc) failed: %s\n",
g10_errstr (rc));
}
free_pubkey_enc(enc);
@@ -951,9 +946,9 @@ encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr)
if (opt.outfile)
{
log_error(_("--output doesn't work for this command\n"));
- return;
+ return;
}
-
+
if (!nfiles)
{
char line[2048];
diff --git a/g10/pkglue.c b/g10/pkglue.c
index 66ba48b60..836c2c3e2 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -37,7 +37,7 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item)
{
gcry_sexp_t list;
gcry_mpi_t data;
-
+
list = gcry_sexp_find_token (sexp, item, 0);
assert (list);
data = gcry_sexp_nth_mpi (list, 1, 0);
@@ -151,10 +151,11 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
+ * PK is only required to compute the fingerprint for ECDH.
*/
int
pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
- const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey)
+ PKT_public_key *pk, gcry_mpi_t *pkey)
{
gcry_sexp_t s_ciph, s_data, s_pkey;
int rc;
@@ -179,15 +180,17 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
if (rc || gcry_sexp_build (&s_data, NULL, "%m", data))
BUG ();
}
- else if (algo == PUBKEY_ALGO_ECDH)
+ else if (algo == PUBKEY_ALGO_ECDH)
{
gcry_mpi_t k;
char *curve;
+ byte fp[MAX_FINGERPRINT_LEN];
+ size_t fpn;
rc = pk_ecdh_generate_ephemeral_key (pkey, &k);
if (rc)
return rc;
-
+
curve = openpgp_oid_to_str (pkey[0]);
if (!curve)
rc = gpg_error_from_syserror ();
@@ -215,12 +218,14 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
if (rc)
;
- else if (algo == PUBKEY_ALGO_ECDH)
+ else if (algo == PUBKEY_ALGO_ECDH)
{
gcry_mpi_t shared, public, result;
+ byte fp[MAX_FINGERPRINT_LEN];
+ size_t fpn;
/* Get the shared point and the ephemeral public key. */
- shared = mpi_from_sexp (s_ciph, "s");
+ shared = mpi_from_sexp (s_ciph, "s");
public = mpi_from_sexp (s_ciph, "e");
gcry_sexp_release (s_ciph);
s_ciph = NULL;
@@ -230,10 +235,14 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
gcry_mpi_dump (public);
log_printf ("\n");
}
-
+
result = NULL;
- rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
- pk_fp, data, pkey, &result);
+ fingerprint_from_pk (pk, fp, &fpn);
+ if (fpn != 20)
+ rc = gpg_error (GPG_ERR_INV_LENGTH);
+ else
+ rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
+ fp, data, pkey, &result);
gcry_mpi_release (shared);
if (!rc)
{
diff --git a/g10/pkglue.h b/g10/pkglue.h
index eb0d7c1dc..e5165f73b 100644
--- a/g10/pkglue.h
+++ b/g10/pkglue.h
@@ -20,14 +20,15 @@
#ifndef GNUPG_G10_PKGLUE_H
#define GNUPG_G10_PKGLUE_H
+#include "packet.h" /* For PKT_public_key. */
+
/*-- pkglue.c --*/
gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item);
int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
gcry_mpi_t *pkey);
int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
- const byte fp[MAX_FINGERPRINT_LEN],
- gcry_mpi_t *pkey);
+ PKT_public_key *pk, gcry_mpi_t *pkey);
int pk_check_secret_key (int algo, gcry_mpi_t *skey);
@@ -35,7 +36,7 @@ int pk_check_secret_key (int algo, gcry_mpi_t *skey);
gcry_mpi_t pk_ecdh_default_params (unsigned int qbits);
gpg_error_t pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k);
gpg_error_t pk_ecdh_encrypt_with_shared_point
-/* */ (int is_encrypt, gcry_mpi_t shared_mpi,
+/* */ (int is_encrypt, gcry_mpi_t shared_mpi,
const byte pk_fp[MAX_FINGERPRINT_LEN],
gcry_mpi_t data, gcry_mpi_t *pkey,
gcry_mpi_t *out);