aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ChangeLog5
-rw-r--r--agent/ChangeLog4
-rw-r--r--agent/cvt-openpgp.c31
-rw-r--r--agent/gpg-agent.c2
-rw-r--r--agent/protect.c37
-rw-r--r--common/convert.c11
-rw-r--r--configure.ac18
-rw-r--r--dirmngr/Makefile.am2
-rw-r--r--g10/armor.c2
-rw-r--r--g10/build-packet.c87
-rw-r--r--g10/ecdh.c451
-rw-r--r--g10/encrypt.c4
-rw-r--r--g10/export.c22
-rw-r--r--g10/gpg.c2
-rw-r--r--g10/keygen.c2
-rw-r--r--g10/keyid.c37
-rw-r--r--g10/main.h16
-rw-r--r--g10/misc.c133
-rw-r--r--g10/parse-packet.c194
-rw-r--r--g10/pkglue.c111
-rw-r--r--g10/pkglue.h16
-rw-r--r--g10/pubkey-enc.c112
-rw-r--r--g10/seskey.c279
-rw-r--r--g10/sign.c30
-rw-r--r--g10/verify-stubs.c9
-rw-r--r--g13/utils.c4
-rw-r--r--include/ChangeLog6
-rw-r--r--include/cipher.h12
-rw-r--r--kbx/keybox-openpgp.c1
29 files changed, 875 insertions, 765 deletions
diff --git a/ChangeLog b/ChangeLog
index 656fe7212..287e4d1c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-21 Werner Koch <[email protected]>
+
+ * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP.
+ (HAVE_GCRY_PK_ECDH): Add new test.
+
2011-01-03 Werner Koch <[email protected]>
* README.SVN: Rename to README.GIT.
diff --git a/agent/ChangeLog b/agent/ChangeLog
index ce1fdccd8..699282754 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,7 @@
+2011-01-21 Werner Koch <[email protected]>
+
+ * 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/cvt-openpgp.c b/agent/cvt-openpgp.c
index 73c31f786..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
@@ -100,8 +107,8 @@ 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.
- pubkey_algo is a libgcrypt ID
+ 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)
@@ -111,7 +118,8 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
*r_key = NULL;
- pubkey_algo = map_pk_openpgp_to_gcry( pubkey_algo );
+ /* FIXME: This is not consistent with the above comment. */
+ pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo);
switch (pubkey_algo)
{
@@ -224,9 +232,9 @@ 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 );
+ /* 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. */
@@ -655,7 +663,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
string = gcry_sexp_nth_string (list, 1);
if (!string)
goto bad_seckey;
- pubkey_algo = gcry_pk_map_name (string); /* ligcrypt IDs */
+ pubkey_algo = gcry_pk_map_name (string);
xfree (string);
if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
@@ -1022,7 +1030,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
}
algo = gcry_pk_map_name (name);
- log_debug ( "convert to openpgp begin for algo=%s\n", name );
xfree (name);
switch (algo)
@@ -1052,7 +1059,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
err = apply_protection (array, npkey, nskey, passphrase,
GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
3, GCRY_MD_SHA1, salt, s2k_count);
- ///log_debug ( "convert to openpgp: after applying protection, err = %d\n", err );
/* Turn it into the transfer key S-expression. Note that we always
return a protected key. */
if (!err)
@@ -1082,8 +1088,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
put_membuf_str (&mbuf, ")\n");
put_membuf (&mbuf, "", 1);
- ///log_debug ( "convert to openpgp: calling gcry_sexp_build\n" );
-
tmpkey = NULL;
{
char *format = get_membuf (&mbuf, NULL);
@@ -1093,7 +1097,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args);
xfree (format);
}
- ///log_debug ( "convert to openpgp: calling gcry_sexp_build before err=%d\n", err );
if (!err)
err = gcry_sexp_build (&tmpsexp, NULL,
"(openpgp-private-key\n"
@@ -1106,7 +1109,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
(int)sizeof protect_iv, protect_iv,
(int)sizeof salt, salt,
countbuf);
- ///log_debug ( "convert to openpgp: after gcry_sexp_build, err = %d\n", err );
gcry_sexp_release (tmpkey);
if (!err)
err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen);
@@ -1116,8 +1118,5 @@ 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]);
- log_debug ( "convert to openpgp end with err=%d\n", err );
-
return err;
}
-
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index d85283a5e..db9039278 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -2304,6 +2304,8 @@ check_for_running_agent (int silent, int mode)
}
/* 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)
{
diff --git a/agent/protect.c b/agent/protect.c
index d14665363..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;
@@ -428,9 +428,6 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char *p;
gcry_md_hd_t md;
- if (opt.debug & DBG_CRYPTO_VALUE)
- log_info ("Protecting key=%s, passphrase=%s\n", plainkey, passphrase);
-
/* Create an S-expression with the protected-at timestamp. */
memcpy (timestamp_exp, "(12:protected-at15:", 19);
gnupg_get_isotime (timestamp_exp+19);
@@ -459,55 +456,41 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
for (infidx=0; protect_info[infidx].algo
&& !smatch (&s, n, protect_info[infidx].algo); infidx++)
;
- if (!protect_info[infidx].algo) {
- log_info ("Unsupported alg %d for protection\n", protect_info[infidx].algo);
+ if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- }
prot_begin = prot_end = NULL;
for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
{
if (i == protect_info[infidx].prot_from)
prot_begin = s;
- if (*s != '(') {
- log_info ("Unbalanced bracket in S-expression #1\n");
+ if (*s != '(')
return gpg_error (GPG_ERR_INV_SEXP);
- }
depth++;
s++;
n = snext (&s);
- if (!n) {
- log_info ("Cannot get the length of S-expression field\n");
+ if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
- }
- if (n != 1 || c != *s) {
- log_info ("Invalid length in S-expression field\n");
+ if (n != 1 || c != *s)
return gpg_error (GPG_ERR_INV_SEXP);
- }
- s += n;
+ s += n;
n = snext (&s);
- if (!n) {
- log_info ("Invalid fieled in S-expression field\n");
+ if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
- }
s +=n; /* skip value */
- if (*s != ')') {
- log_info ("Unbalanced bracket in S-expression #2\n");
+ if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP);
- }
depth--;
if (i == protect_info[infidx].prot_to)
prot_end = s;
s++;
}
- if (*s != ')' || !prot_begin || !prot_end ) {
- log_info ("Unbalanced bracket in S-expression #3\n");
+ if (*s != ')' || !prot_begin || !prot_end )
return gpg_error (GPG_ERR_INV_SEXP);
- }
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)
diff --git a/common/convert.c b/common/convert.c
index 0a0c46f8e..5df6b335e 100644
--- a/common/convert.c
+++ b/common/convert.c
@@ -23,7 +23,7 @@
#include <ctype.h>
#include "util.h"
-#include "gcrypt.h"
+#include "gcrypt.h" /* FIXME: really needed? */
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
@@ -250,7 +250,10 @@ hex2str_alloc (const char *hexstring, size_t *r_count)
* caller must free with xfree
* Returns NULL on error, never throws
*/
-char *mpi2hex( gcry_mpi_t m ) {
+char *
+mpi2hex( gcry_mpi_t m )
+{
+#warning we have code for this in libcrypt
size_t nbytes;
size_t nbytes2;
int rc;
@@ -270,7 +273,9 @@ char *mpi2hex( gcry_mpi_t m ) {
bin2hex( p+2*nbytes+1, nbytes2, p );
p[nbytes2*2] = '\0';
-//printf("%s:%d>>>> Created the string %s from %d bytes %02x %02x ..., MPI was %d bytes\n", __FILE__, __LINE__, p, nbytes2, p[2*nbytes+1], p[2*nbytes+2], nbytes);
+ /*printf("%s:%d>>>> Created the string %s from %d bytes %02x %02x
+ ..., MPI was %d bytes\n", __FILE__, __LINE__, p, nbytes2,
+ p[2*nbytes+1], p[2*nbytes+2], nbytes); */
return p;
}
diff --git a/configure.ac b/configure.ac
index 575c1ec08..ef6d2f9d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@ min_automake_version="1.10"
# Remember to change the version number immediately *after* a release.
# Set my_issvn to "yes" for non-released code. Remember to run an
# "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [2.2.0])
+m4_define([my_version], [2.1.0])
m4_define([my_issvn], [yes])
m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \
@@ -43,7 +43,7 @@ development_version=no
NEED_GPG_ERROR_VERSION=1.8
NEED_LIBGCRYPT_API=1
-NEED_LIBGCRYPT_VERSION=1.6.0
+NEED_LIBGCRYPT_VERSION=1.4.6
NEED_LIBASSUAN_API=2
NEED_LIBASSUAN_VERSION=2.0.0
@@ -724,6 +724,20 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
have_libgcrypt=yes,have_libgcrypt=no)
+AC_CACHE_CHECK([whether Libgcrypt support ECDH], gnupg_cv_gcry_pk_ecdh,
+ [ _gnupg_gcry_save_cflags=$CFLAGS
+ CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
+ AC_TRY_COMPILE(
+ [#include <gcrypt>],
+ [ return GCRY_PK_ECDH; ],
+ gnupg_cv_gcry_pk_ecdh=yes,
+ gnupg_cv_gcry_pk_ecdh=no)
+ CFLAGS=$_gnupg_gcry_save_cflags])
+if test "$gnupg_cv_gcry_pk_ecdh" = yes; then
+ AC_DEFINE([HAVE_GCRY_PK_ECDH], 1,
+ [Define if gcrypt.h has the enum value for ECDH.])
+fi
+
#
# libassuan is used for IPC
diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index 0285fc8f8..128d7c383 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -61,7 +61,7 @@ endif
dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBINTL) $(LIBICONV)
if !USE_LDAPWRAPPER
-dirmngr_LDADD += $(LDAPLIBS) -llber
+dirmngr_LDADD += $(LDAPLIBS) -llber #FIXME: Test for liblber first.
endif
dirmngr_LDFLAGS = $(extra_bin_ldflags)
diff --git a/g10/armor.c b/g10/armor.c
index 8cfd35c1f..a6195fc3d 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -1079,7 +1079,7 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a,afx->eol);
if( !opt.no_version )
{
- iobuf_writestr(a, "Version: GnuPG v" VERSION "-ecc ("
+ iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")" );
iobuf_writestr(a,afx->eol);
}
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 3a2c206c8..d138e0614 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -178,21 +178,20 @@ mpi_write (iobuf_t out, gcry_mpi_t a)
return rc;
}
-/*
- * Write the name OID, encoded as an mpi, to OUT. The format of the content of the MPI is
- * one byte LEN, following by LEN bytes that are DER representation of an ASN.1 OID.
- * This is true for each of the 3 following functions.
- */
+/* Write the name OID, encoded as an mpi, to OUT. The format of the
+ * content of the MPI is one byte LEN, following by LEN bytes that are
+ * DER representation of an ASN.1 OID. This is true for each of the 3
+ * following functions. */
#define iobuf_name_oid_write iobuf_write_size_body_mpi
+
/* Write the value of KEK fields for ECDH. */
#define ecdh_kek_params_write iobuf_write_size_body_mpi
-/* Write the value of encrypted filed for ECDH. */
+
+/* Write the value of encrypted filed for ECDH. */
#define ecdh_esk_write iobuf_write_size_body_mpi
-/****************
- * calculate the length of a packet described by PKT
- */
+/* Calculate the length of a packet described by PKT. */
u32
calc_packet_length( PACKET *pkt )
{
@@ -300,24 +299,35 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
}
assert (npkey < nskey);
- if( pk->pubkey_algo != PUBKEY_ALGO_ECDSA && pk->pubkey_algo != PUBKEY_ALGO_ECDH ) {
- /* Writing the public parameters is easy, */
- for (i=0; i < npkey; i++ )
- if ((err = mpi_write (a, pk->pkey[i])))
- goto leave;
- }
- else {
- /* ... except we do an adjustment for ECC OID and possibly KEK params for ECDH */
- if( (err=iobuf_name_oid_write(a, pk->pkey[0])) || /* DER of OID with preceeding length byte */
- (err = mpi_write (a, pk->pkey[1])) ) /* point Q, the public key */
+ /* Writing the public parameters is easy. Except if we do an
+ adjustment for ECC OID and possibly KEK params for ECDH. */
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- goto leave;
+ /* Write DER of OID with preceeding length byte. */
+ err = iobuf_name_oid_write (a, pk->pkey[0]);
+ if (err)
+ goto leave;
+ /* Write point Q, the public key. */
+ err = mpi_write (a, pk->pkey[1]);
+ if (err)
+ goto leave;
+
+ /* Write one more public field for ECDH. */
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ {
+ err = ecdh_kek_params_write(a,pk->pkey[2]);
+ if (err)
+ goto leave;
+ }
}
- if( pk->pubkey_algo == PUBKEY_ALGO_ECDH && (err=ecdh_kek_params_write(a,pk->pkey[2]))) { /* one more public field for ECDH */
- goto leave;
+ else
+ {
+ for (i=0; i < npkey; i++ )
+ if ((err = mpi_write (a, pk->pkey[i])))
+ goto leave;
}
- /* followed by possibly protected private scalar */
- }
+
if (pk->seckey_info)
{
@@ -483,22 +493,25 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
if ( !n )
write_fake_data( a, enc->data[0] );
- if( enc->pubkey_algo != PUBKEY_ALGO_ECDH ) {
- for (i=0; i < n && !rc ; i++ )
- rc = mpi_write(a, enc->data[i] );
- }
- else {
- /* the second field persists as a LEN+field structure, even though it is
- * stored for uniformity as an MPI internally */
- assert( n==2 );
- rc = mpi_write(a, enc->data[0] );
- if( !rc ) rc = ecdh_esk_write(a, enc->data[1] );
- }
+ if (enc->pubkey_algo == PUBKEY_ALGO_ECDH )
+ {
+ /* The second field persists as a LEN+field structure, even
+ * though it is stored for uniformity as an MPI internally. */
+ assert (n == 2);
+ rc = mpi_write (a, enc->data[0]);
+ if (!rc)
+ rc = ecdh_esk_write (a, enc->data[1]);
+ }
+ else
+ {
+ for (i=0; i < n && !rc ; i++ )
+ rc = mpi_write(a, enc->data[i] );
+ }
if (!rc)
{
- write_header(out, ctb, iobuf_get_temp_length(a) );
- rc = iobuf_write_temp( out, a );
+ write_header (out, ctb, iobuf_get_temp_length(a) );
+ rc = iobuf_write_temp (out, a);
}
iobuf_close(a);
return rc;
diff --git a/g10/ecdh.c b/g10/ecdh.c
index 091a28cde..cb251fef2 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) 2000, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -31,10 +31,12 @@
#include "options.h"
gcry_mpi_t
-pk_ecdh_default_params_to_mpi( int qbits ) {
+pk_ecdh_default_params_to_mpi (int qbits)
+{
gpg_error_t err;
gcry_mpi_t result;
- /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */
+ /* Defaults are the strongest possible choices. Performance is not
+ an issue here, only interoperability. */
byte kek_params[4] = {
3 /*size of following field*/,
1 /*fixed version for KDF+AESWRAP*/,
@@ -50,41 +52,49 @@ pk_ecdh_default_params_to_mpi( int qbits ) {
} kek_params_table[] = {
{ 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES },
{ 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
- { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary
+
+ /* Note: 528 is 521 rounded to the 8 bit boundary */
+ { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
};
- for( i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++ ) {
- if( kek_params_table[i].qbits >= qbits ) {
- kek_params[2] = kek_params_table[i].openpgp_hash_id;
- kek_params[3] = kek_params_table[i].openpgp_cipher_id;
- break;
+ for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
+ {
+ if (kek_params_table[i].qbits >= qbits)
+ {
+ kek_params[2] = kek_params_table[i].openpgp_hash_id;
+ kek_params[3] = kek_params_table[i].openpgp_cipher_id;
+ break;
+ }
}
- }
- if( DBG_CIPHER )
- log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) );
+ if (DBG_CIPHER)
+ log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) );
- err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, kek_params, sizeof(kek_params), NULL);
+ err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
+ kek_params, sizeof(kek_params), NULL);
if (err)
log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
return result;
}
-/* returns allocated (binary) KEK parameters; the size is returned in sizeout.
- * The caller must free returned value with xfree.
- * Returns NULL on error
+
+/* Returns allocated (binary) KEK parameters; the size is returned in
+ * sizeout. The caller must free the returned value with xfree.
+ * Returns NULL on error.
*/
byte *
-pk_ecdh_default_params( int qbits, size_t *sizeout ) {
- /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */
+pk_ecdh_default_params (int qbits, size_t *sizeout)
+{
+ /* Defaults are the strongest possible choices. Performance is not
+ an issue here, only interoperability. */
byte kek_params[4] = {
3 /*size of following field*/,
1 /*fixed version for KDF+AESWRAP*/,
DIGEST_ALGO_SHA512 /* KEK MD */,
- CIPHER_ALGO_AES256 /*KEK AESWRAP alg*/
+ CIPHER_ALGO_AES256 /* KEK AESWRAP alg */
};
int i;
-
+
static const struct {
int qbits;
int openpgp_hash_id;
@@ -92,39 +102,48 @@ pk_ecdh_default_params( int qbits, size_t *sizeout ) {
} kek_params_table[] = {
{ 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES },
{ 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
- { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary
+ /* Note: 528 is 521 rounded to the 8 bit boundary */
+ { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
};
byte *p;
*sizeout = 0;
-
- for( i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++ ) {
- if( kek_params_table[i].qbits >= qbits ) {
- kek_params[2] = kek_params_table[i].openpgp_hash_id;
- kek_params[3] = kek_params_table[i].openpgp_cipher_id;
- break;
+
+ for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
+ {
+ if (kek_params_table[i].qbits >= qbits)
+ {
+ kek_params[2] = kek_params_table[i].openpgp_hash_id;
+ kek_params[3] = kek_params_table[i].openpgp_cipher_id;
+ break;
+ }
}
- }
- if( DBG_CIPHER )
- log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) );
+ if (DBG_CIPHER )
+ log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params));
- p = xtrymalloc( sizeof(kek_params) );
- if( p == NULL )
+ p = xtrymalloc (sizeof(kek_params));
+ if (!p)
return NULL;
- memcpy( p, kek_params, sizeof(kek_params) );
+ memcpy (p, kek_params, sizeof(kek_params));
*sizeout = sizeof(kek_params);
return p;
}
-/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC point using FIPS SP 800-56A compliant method, which is
- * key derivation + key wrapping. The direction is determined by the first parameter (is_encrypt=1 --> this is encryption).
- * The result is returned in out as a size+value MPI.
+
+/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC
+ * point using FIPS SP 800-56A compliant method, which is key
+ * derivation + key wrapping. The direction is determined by the first
+ * parameter (is_encrypt=1 --> this is encryption). The result is
+ * returned in out as a size+value MPI.
+ *
* TODO: memory leaks (x_secret).
*/
static int
-pk_ecdh_encrypt_with_shared_point ( 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)
+pk_ecdh_encrypt_with_shared_point (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)
{
byte *secret_x;
int secret_x_size;
@@ -141,55 +160,70 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi,
{
size_t nbytes;
- /* extract x component of the shared point: this is the actual shared secret */
+ /* Extract x component of the shared point: this is the actual
+ shared secret */
nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8;
secret_x = xmalloc_secure( nbytes );
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, &nbytes, shared_mpi);
- if( rc ) {
- xfree( secret_x );
- log_error ("ec ephemeral export of shared point failed: %s\n", gpg_strerror (rc) );
- return rc;
- }
+ rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes,
+ &nbytes, shared_mpi);
+ if (rc)
+ {
+ xfree (secret_x);
+ log_error ("ec ephemeral export of shared point failed: %s\n",
+ gpg_strerror (rc));
+ return rc;
+ }
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 );
+ 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 );
+ if (DBG_CIPHER)
+ log_printhex ("ecdh shared secret X is:", secret_x, secret_x_size );
}
- /*** We have now the shared secret bytes in secret_x ***/
+ /*** We have now the shared secret bytes in secret_x. ***/
- /* At this point we are done with PK encryption and the rest of the function uses symmetric
- * key encryption techniques to protect the input 'data'. The following two sections will
- * simply replace current secret_x with a value derived from it. This will become a KEK.
+ /* At this point we are done with PK encryption and the rest of the
+ * function uses symmetric key encryption techniques to protect the
+ * input 'data'. The following two sections will simply replace
+ * current secret_x with a value derived from it. This will become
+ * a KEK.
*/
{
IOBUF obuf = iobuf_temp();
rc = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */
+
+ kdf_params_size = iobuf_temp_to_buffer (obuf,
+ kdf_params, sizeof(kdf_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 );
+ if (DBG_CIPHER)
+ log_printhex ("ecdh KDF public key params are:",
+ kdf_params, kdf_params_size );
- if( kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1 ) /* expect 4 bytes 03 01 hash_alg symm_alg */
+ /* 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 (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 )
+ 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 )
+ 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 */
+ /* Build kdf_params. */
{
IOBUF obuf;
@@ -205,13 +239,15 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi,
/* 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) );
- iobuf_close( obuf );
- if( rc ) {
+ kdf_params_size = iobuf_temp_to_buffer (obuf,
+ kdf_params, sizeof(kdf_params));
+ iobuf_close (obuf);
+ if (rc)
return rc;
- }
- if( DBG_CIPHER )
- log_printhex ("ecdh KDF message params are:", kdf_params, kdf_params_size );
+
+ if(DBG_CIPHER)
+ log_printhex ("ecdh KDF message params are:",
+ kdf_params, kdf_params_size );
}
/* Derive a KEK (key wrapping key) using kdf_params and secret_x. */
@@ -231,7 +267,8 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi,
assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 );
- memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), gcry_md_get_algo_dlen (kdf_hash_algo));
+ memcpy (secret_x, gcry_md_read (h, kdf_hash_algo),
+ gcry_md_get_algo_dlen (kdf_hash_algo));
gcry_md_close (h);
old_size = secret_x_size;
@@ -239,12 +276,13 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi,
secret_x_size = gcry_cipher_get_algo_keylen( kdf_encr_algo );
assert( secret_x_size <= gcry_md_get_algo_dlen (kdf_hash_algo) );
- memset( secret_x+secret_x_size, old_size-secret_x_size, 0 ); /* we could have allocated more, so clean the tail before returning */
- if( DBG_CIPHER )
+ /* We could have allocated more, so clean the tail before returning. */
+ memset( secret_x+secret_x_size, old_size-secret_x_size, 0 );
+ if (DBG_CIPHER)
log_printhex ("ecdh KEK is:", secret_x, secret_x_size );
- }
-
- /* And, finally, aeswrap with key secret_x */
+ }
+
+ /* And, finally, aeswrap with key secret_x. */
{
gcry_cipher_hd_t hd;
size_t nbytes;
@@ -256,115 +294,134 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi,
rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
if (rc)
- {
- log_error( "ecdh failed to initialize AESWRAP: %s\n", gpg_strerror (rc));
- return rc;
- }
+ {
+ log_error ("ecdh failed to initialize AESWRAP: %s\n",
+ gpg_strerror (rc));
+ return rc;
+ }
rc = gcry_cipher_setkey (hd, secret_x, secret_x_size);
xfree( secret_x );
if (rc)
- {
- gcry_cipher_close (hd);
- log_error("ecdh failed in gcry_cipher_setkey: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- data_buf_size = (gcry_mpi_get_nbits(data)+7)/8;
- assert( (data_buf_size & 7) == (is_encrypt ? 0 : 1) );
-
- data_buf = xmalloc_secure( 1 + 2*data_buf_size + 8 );
- if( !data_buf ) {
- gcry_cipher_close (hd);
- return GPG_ERR_ENOMEM;
- }
-
- if( is_encrypt ) {
- byte *in = data_buf+1+data_buf_size+8;
-
- /* write data MPI into the end of data_buf. data_buf is size aeswrap data */
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, in, data_buf_size, &nbytes, data/*in*/);
- if( rc ) {
- log_error("ecdh failed to export DEK: %s\n", gpg_strerror (rc));
+ {
gcry_cipher_close (hd);
- xfree( data_buf );
+ log_error ("ecdh failed in gcry_cipher_setkey: %s\n",
+ gpg_strerror (rc));
return rc;
}
- if( DBG_CIPHER )
- log_printhex ("ecdh encrypting :", in, data_buf_size );
+ data_buf_size = (gcry_mpi_get_nbits(data)+7)/8;
+ assert ((data_buf_size & 7) == (is_encrypt ? 0 : 1));
- rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, in, data_buf_size);
- memset( in, 0, data_buf_size);
- gcry_cipher_close (hd);
- if(rc)
+ data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8);
+ if (!data_buf)
{
- log_error("ecdh failed in gcry_cipher_encrypt: %s\n", gpg_strerror (rc));
- xfree( data_buf );
- return rc;
+ gcry_cipher_close (hd);
+ return GPG_ERR_ENOMEM;
}
- data_buf[0] = data_buf_size+8;
-
- if( DBG_CIPHER )
- log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
- rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, data_buf, 1+data_buf[0], NULL); /* (byte)size + aeswrap of DEK */
- xfree( data_buf );
- if(rc)
+ if (is_encrypt)
{
- log_error("ecdh failed to create an MPI: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- *out = result;
- }
- else {
- byte *in;
+ byte *in = data_buf+1+data_buf_size+8;
+
+ /* Write data MPI into the end of data_buf. data_buf is size
+ aeswrap data. */
+ rc = gcry_mpi_print (GCRYMPI_FMT_USG, in,
+ data_buf_size, &nbytes, data/*in*/);
+ if (rc)
+ {
+ log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (rc));
+ gcry_cipher_close (hd);
+ xfree (data_buf);
+ return rc;
+ }
+
+ if (DBG_CIPHER)
+ log_printhex ("ecdh encrypting :", in, data_buf_size );
+
+ rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
+ in, data_buf_size);
+ memset (in, 0, data_buf_size);
+ gcry_cipher_close (hd);
+ if (rc)
+ {
+ log_error ("ecdh failed in gcry_cipher_encrypt: %s\n",
+ gpg_strerror (rc));
+ xfree (data_buf);
+ return rc;
+ }
+ data_buf[0] = data_buf_size+8;
+
+ if (DBG_CIPHER)
+ log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
- rc = 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 ) {
- log_error("ecdh inconsistent size\n");
+ rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
+ data_buf, 1+data_buf[0], NULL);
+ /* (byte)size + aeswrap of DEK */
xfree( data_buf );
- return GPG_ERR_BAD_MPI;
+ if (rc)
+ {
+ log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (rc));
+ return rc;
+ }
+
+ *out = result;
}
+ else
+ {
+ byte *in;
+
+ rc = 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)
+ {
+ 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 );
- rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, data_buf_size );
+ if (DBG_CIPHER)
+ log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
+
+ rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
+ data_buf_size);
gcry_cipher_close (hd);
- if(rc)
- {
- log_error("ecdh failed in gcry_cipher_decrypt: %s\n", gpg_strerror (rc));
- xfree( data_buf );
- return rc;
- }
-
- 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;
- //}
+ if (rc)
+ {
+ log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
+ gpg_strerror (rc));
+ xfree (data_buf);
+ return rc;
+ }
+
+ 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; */
+ /* } */
rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
- xfree( data_buf );
- if(rc)
- {
- log_error("ecdh failed to create a plain text MPI: %s\n", gpg_strerror (rc));
- return rc;
- }
-
+ xfree (data_buf);
+ if (rc)
+ {
+ log_error ("ecdh failed to create a plain text MPI: %s\n",
+ gpg_strerror (rc));
+ return rc;
+ }
+
*out = result;
- }
+ }
}
-
+
return rc;
}
@@ -380,21 +437,22 @@ gen_k (unsigned nbits)
gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM);
- if( DBG_CIPHER ) {
- unsigned char *buffer;
- if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k))
- BUG ();
- log_debug("ephemeral scalar MPI #0: %s\n", buffer);
- gcry_free( buffer );
- }
+ if (DBG_CIPHER)
+ {
+ unsigned char *buffer;
+ if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k))
+ BUG ();
+ log_debug("ephemeral scalar MPI #0: %s\n", buffer);
+ gcry_free( buffer );
+ }
return k;
}
-/* Perform ECDH encryption, which involves ECDH key generation.
- */
+/* Perform ECDH encryption, which involves ECDH key generation. */
int
-pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey)
+pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
+ gcry_mpi_t data, gcry_mpi_t * pkey)
{
gcry_sexp_t s_ciph, s_data, s_pkey;
@@ -402,9 +460,9 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr
int rc;
gcry_mpi_t k;
- nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey );
+ nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
- /*** Generate an ephemeral key, actually, a scalar ***/
+ /*** Generate an ephemeral key, actually, a scalar. ***/
k = gen_k (nbits);
if( k == NULL )
@@ -414,50 +472,63 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr
* Now use ephemeral secret to get the shared secret. ***/
rc = gcry_sexp_build (&s_pkey, NULL,
- "(public-key(ecdh(c%m)(q%m)(p%m)))", pkey[0], pkey[1], pkey[2]);
+ "(public-key(ecdh(c%m)(q%m)(p%m)))",
+ pkey[0], pkey[1], pkey[2]);
if (rc)
BUG ();
- /* put the data into a simple list */
- if (gcry_sexp_build (&s_data, NULL, "%m", k)) /* ephemeral scalar goes as data */
+ /* Put the data into a simple list. */
+ /* Ephemeral scalar goes as data. */
+ if (gcry_sexp_build (&s_data, NULL, "%m", k))
BUG ();
- /* pass it to libgcrypt */
+ /* Pass it to libgcrypt. */
rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
gcry_sexp_release (s_data);
gcry_sexp_release (s_pkey);
if (rc)
return rc;
- /* finally, perform encryption */
+ /* Finally, perform encryption. */
{
- gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* ... and get the shared point */
+ /* ... and get the shared point/ */
+ gcry_mpi_t shared;
+
+ shared = mpi_from_sexp (s_ciph, "a");
gcry_sexp_release (s_ciph);
- resarr[0] = mpi_from_sexp (s_ciph, "b"); /* ephemeral public key */
+ /* Ephemeral public key. */
+ resarr[0] = mpi_from_sexp (s_ciph, "b");
- if( DBG_CIPHER ) {
+ if (DBG_CIPHER)
+ {
unsigned char *buffer;
+
if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0]))
BUG ();
log_debug("ephemeral key MPI: %s\n", buffer);
gcry_free( buffer );
- }
-
- rc = pk_ecdh_encrypt_with_shared_point ( 1 /*=encrypton*/, shared, pk_fp, data, pkey, resarr+1 );
- mpi_release( shared );
+ }
+
+ rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
+ pk_fp, data, pkey, resarr+1);
+ mpi_release (shared);
}
-
+
return rc;
}
-/* Perform ECDH decryption.
- */
+
+/* Perform ECDH decryption. */
int
-pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey) {
+pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN],
+ gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey)
+{
if (!data)
return gpg_error (GPG_ERR_BAD_MPI);
- return pk_ecdh_encrypt_with_shared_point ( 0 /*=decryption*/, shared, sk_fp, data/*encr data as an MPI*/, skey, result );
+ return pk_ecdh_encrypt_with_shared_point (0 /*=decryption*/, shared,
+ sk_fp, data/*encr data as an MPI*/,
+ skey, result);
}
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 3c16309d0..f52921582 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -894,8 +894,8 @@ 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 );
+ 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
diff --git a/g10/export.c b/g10/export.c
index 82d97511f..74a7b0c51 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1161,18 +1161,16 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
/* iobuf_put (out,')'); iobuf_put (out,'\n'); */
/* (*indent)--; */
/* } */
-/*
- else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected)
- {
- write_sexp_line (out, indent, "(ecdsa\n");
- (*indent)++;
- write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n');
- write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n');
- write_sexp_keyparm (out, indent, "d", sk->skey[7]);
- iobuf_put (out,')'); iobuf_put (out,'\n');
- (*indent)--;
- }
-*/
+ /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */
+ /* { */
+ /* write_sexp_line (out, indent, "(ecdsa\n"); */
+ /* (*indent)++; */
+ /* write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */
+ /* write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */
+ /* write_sexp_keyparm (out, indent, "d", sk->skey[7]); */
+ /* iobuf_put (out,')'); iobuf_put (out,'\n'); */
+ /* (*indent)--; */
+ /* } */
/* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
/* { */
/* write_sexp_line (out, indent, "(elg\n"); */
diff --git a/g10/gpg.c b/g10/gpg.c
index 23b193402..3794aa2b7 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -813,7 +813,7 @@ my_strusage( int level )
const char *p;
switch( level ) {
- case 11: p = "gpg (GnuPG) ecc";
+ case 11: p = "gpg (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
diff --git a/g10/keygen.c b/g10/keygen.c
index f7f152659..e75da792e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -18,6 +18,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#warning wk: check these changes.
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,7 +44,6 @@
#include "keyserver-internal.h"
#include "call-agent.h"
#include "pkglue.h"
-#include "gcrypt.h"
/* The default algorithms. If you change them remember to change them
also in gpg.c:gpgconf_list. You should also check that the value
diff --git a/g10/keyid.c b/g10/keyid.c
index 2a9bd1988..0405b8b2f 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -54,11 +54,11 @@ pubkey_letter( int algo )
case PUBKEY_ALGO_RSA: return 'R' ;
case PUBKEY_ALGO_RSA_E: return 'r' ;
case PUBKEY_ALGO_RSA_S: return 's' ;
- case PUBKEY_ALGO_ELGAMAL_E: return 'g';
+ case PUBKEY_ALGO_ELGAMAL_E: return 'g' ;
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
case PUBKEY_ALGO_DSA: return 'D' ;
- case PUBKEY_ALGO_ECDSA: return 'E' ; // ECC DSA (sign only)
- case PUBKEY_ALGO_ECDH: return 'e' ; // ECC DH (encrypt only)
+ case PUBKEY_ALGO_ECDSA: return 'E' ; /* ECC DSA (sign only) */
+ case PUBKEY_ALGO_ECDH: return 'e' ; /* ECC DH (encrypt only) */
default: return '?';
}
}
@@ -76,8 +76,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
unsigned int nbits;
size_t nbytes;
int npkey = pubkey_get_npkey (pk->pubkey_algo);
- /* name OID, MPI of public point, [for ECDH only: KEK params] */
- enum gcry_mpi_format ecc_pub_format[3] = {GCRYMPI_FMT_USG, GCRYMPI_FMT_PGP, GCRYMPI_FMT_USG};
/* Two extra bytes for the expiration date in v3 */
if(pk->version<4)
@@ -92,11 +90,17 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
}
else
{
- for(i=0; i < npkey; i++ )
+ for (i=0; i < npkey; i++ )
{
- const enum gcry_mpi_format fmt =
- ((pk->pubkey_algo==PUBKEY_ALGO_ECDSA || pk->pubkey_algo==PUBKEY_ALGO_ECDH) ? ecc_pub_format[i] : GCRYMPI_FMT_PGP);
-
+ enum gcry_mpi_format fmt;
+
+ 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. */
+ else
+ fmt = GCRYMPI_FMT_PGP;
+
if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i]))
BUG ();
pp[i] = xmalloc (nbytes);
@@ -106,7 +110,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
n += nn[i];
}
}
-
+
gcry_md_putc ( md, 0x99 ); /* ctb */
/* What does it mean if n is greater than than 0xFFFF ? */
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
@@ -724,13 +728,12 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
"(public-key(ecc(c%m)(q%m)))",
pk->pkey[0], pk->pkey[1]);
break;
-/*
- case PUBKEY_ALGO_ECDH:
- err = gcry_sexp_build (&s_pkey, NULL,
- "(public-key(ecdh(c%m)(q%m)(p%m)))",
- pk->pkey[0], pk->pkey[1], pk->pkey[2]);
- break;
-*/
+
+ /* case PUBKEY_ALGO_ECDH: */
+ /* err = gcry_sexp_build (&s_pkey, NULL, */
+ /* "(public-key(ecdh(c%m)(q%m)(p%m)))", */
+ /* pk->pkey[0], pk->pkey[1], pk->pkey[2]); */
+ /* break; */
default:
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
diff --git a/g10/main.h b/g10/main.h
index e336e5ce6..c7980ac9a 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -87,9 +87,12 @@ u16 checksum_mpi( gcry_mpi_t a );
u32 buffer_to_u32( const byte *buffer );
const byte *get_session_marker( size_t *rlen );
int map_cipher_openpgp_to_gcry (int algo);
-#define openpgp_cipher_open(_a,_b,_c,_d) gcry_cipher_open((_a),map_cipher_openpgp_to_gcry((_b)),(_c),(_d))
-#define openpgp_cipher_get_algo_keylen(_a) gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a)))
-#define openpgp_cipher_get_algo_blklen(_a) gcry_cipher_get_algo_blklen(map_cipher_openpgp_to_gcry((_a)))
+#define openpgp_cipher_open(_a,_b,_c,_d) \
+ gcry_cipher_open((_a),map_cipher_openpgp_to_gcry((_b)),(_c),(_d))
+#define openpgp_cipher_get_algo_keylen(_a) \
+ gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a)))
+#define openpgp_cipher_get_algo_blklen(_a) \
+ gcry_cipher_get_algo_blklen(map_cipher_openpgp_to_gcry((_a)))
int openpgp_cipher_blocklen (int algo);
int openpgp_cipher_test_algo( int algo );
const char *openpgp_cipher_algo_name (int algo);
@@ -159,7 +162,8 @@ int pubkey_get_nenc( int algo );
unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey );
int mpi_print (estream_t stream, gcry_mpi_t a, int mode);
int iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a);
-int iobuf_read_size_body(iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out);
+int iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size,
+ int pktlen, gcry_mpi_t *out);
int ecdsa_qbits_from_Q( int qbits );
@@ -258,7 +262,9 @@ int save_unprotected_key_to_card (PKT_public_key *sk, int keyno);
#define KEYGEN_FLAG_NO_PROTECTION 1
#define KEYGEN_FLAG_TRANSIENT_KEY 2
-int pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits);
+int pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo,
+ int keygen_flags, char **cache_nonce_addr,
+ unsigned nbits);
/*-- openfile.c --*/
int overwrite_filep( const char *fname );
diff --git a/g10/misc.c b/g10/misc.c
index a09636b60..6f77119fe 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1,6 +1,6 @@
/* misc.c - miscellaneous functions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- * 2008, 2009 Free Software Foundation, Inc.
+ * 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -366,10 +366,17 @@ map_cipher_gcry_to_openpgp (int algo)
}
}
+/* Map OpenPGP public key algorithm numbers to those used by
+ Libgcrypt. */
int
map_pk_openpgp_to_gcry (int algo)
{
- return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo));
+ switch (algo)
+ {
+ case PUBKEY_ALGO_ECDSA: return GCRY_PK_ECDSA;
+ case PUBKEY_ALGO_ECDH: return GCRY_PK_ECDH;
+ default: return algo;
+ }
}
@@ -416,13 +423,7 @@ openpgp_cipher_test_algo( int algo )
const char *
openpgp_cipher_algo_name (int algo)
{
- return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
-}
-
-const char *
-openpgp_pk_algo_name (int algo)
-{
- return gcry_pk_algo_name ( algo == PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : ( algo == PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo ) );
+ return gnupg_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
}
int
@@ -438,12 +439,7 @@ openpgp_pk_test_algo( int algo )
if (algo < 0 || algo > 110)
return gpg_error (GPG_ERR_PUBKEY_ALGO);
- if( algo == PUBKEY_ALGO_ECDSA )
- algo = GCRY_PK_ECDSA;
- else if( algo == PUBKEY_ALGO_ECDH )
- algo = GCRY_PK_ECDH;
-
- return gcry_pk_test_algo ( algo );
+ return gcry_pk_test_algo (map_pk_openpgp_to_gcry (algo));
}
int
@@ -461,12 +457,8 @@ openpgp_pk_test_algo2( int algo, unsigned int use )
if (algo < 0 || algo > 110)
return gpg_error (GPG_ERR_PUBKEY_ALGO);
- if( algo == PUBKEY_ALGO_ECDSA )
- algo = GCRY_PK_ECDSA;
- else if( algo == PUBKEY_ALGO_ECDH )
- algo = GCRY_PK_ECDH;
-
- return gcry_pk_algo_info ( algo, GCRYCTL_TEST_ALGO, NULL, &use_buf);
+ return gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo),
+ GCRYCTL_TEST_ALGO, NULL, &use_buf);
}
int
@@ -507,10 +499,12 @@ openpgp_pk_algo_usage ( int algo )
/* Map the OpenPGP pubkey algorithm whose ID is contained in ALGO to a
string representation of the algorithm name. For unknown algorithm
- IDs this function returns "?".
+ IDs this function returns "?". */
const char *
openpgp_pk_algo_name (int algo)
{
+ /* We use fixed strings to have pretty names instead of those from
+ libgcrypt. */
switch (algo)
{
case PUBKEY_ALGO_RSA:
@@ -522,10 +516,13 @@ openpgp_pk_algo_name (int algo)
case PUBKEY_ALGO_DSA: return "dsa";
- default: return "?";
+ case PUBKEY_ALGO_ECDSA:return "ecdsa";
+
+ case PUBKEY_ALGO_ECDH: return "ecdh";
+
+ default: gcry_pk_algo_name (map_pk_openpgp_to_gcry (algo));
}
}
-*/
int
@@ -1444,6 +1441,7 @@ pubkey_nbits( int algo, gcry_mpi_t *key )
int rc, nbits;
gcry_sexp_t sexp;
+#warning Why this assert
assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH );
if( algo == GCRY_PK_DSA ) {
@@ -1506,10 +1504,12 @@ mpi_print (estream_t fp, gcry_mpi_t a, int mode)
return n;
}
+
/*
- * Write a special size+body mpi a, to OUT. The format of the content of the MPI is
- * one byte LEN, following by LEN bytes
+ * Write a special size+body mpi A, to OUT. The format of the content
+ * of the MPI is one byte LEN, following by LEN bytes.
*/
+/* FIXME: Rename this function: it is not in iobuf.c */
int
iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a)
{
@@ -1538,57 +1538,68 @@ iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a)
return iobuf_write( out, buffer, nbytes );
}
+
/*
- * Read a special size+body from inp into body[body_max_size] and return it in a buffer and as MPI.
- * On success the number of consumed bytes will body[0]+1.
- * The format of the content of the returned MPI is one byte LEN, following by LEN bytes.
- * Caller is expected to pre-allocate fixed-size 255 byte buffer (or smaller when appropriate).
+ * Read a special size+body from inp into body[body_max_size] and
+ * return it in a buffer and as MPI. On success the number of
+ * consumed bytes will body[0]+1. The format of the content of the
+ * returned MPI is one byte LEN, following by LEN bytes. Caller is
+ * expected to pre-allocate fixed-size 255 byte buffer (or smaller
+ * when appropriate).
*/
+/* FIXME: Rename this function: it is not in iobuf.c */
int
-iobuf_read_size_body( iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out ) {
+iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size,
+ int pktlen, gcry_mpi_t *out )
+{
unsigned n;
int rc;
gcry_mpi_t result;
*out = NULL;
- if( (n = iobuf_readbyte(inp)) == -1 ) {
- return G10ERR_INVALID_PACKET;
- }
- if( n >= body_max_size || n < 2) {
- log_error("invalid size+body field\n");
- return G10ERR_INVALID_PACKET;
- }
+ if( (n = iobuf_readbyte(inp)) == -1 )
+ {
+ return G10ERR_INVALID_PACKET;
+ }
+ if ( n >= body_max_size || n < 2)
+ {
+ log_error("invalid size+body field\n");
+ return G10ERR_INVALID_PACKET;
+ }
body[0] = n;
- if( (n = iobuf_read(inp, body+1, n)) == -1 ) {
- log_error("invalid size+body field\n");
- return G10ERR_INVALID_PACKET;
- }
- if( n+1 > pktlen ) {
- log_error("size+body field is larger than the packet\n");
- return G10ERR_INVALID_PACKET;
- }
+ if ((n = iobuf_read(inp, body+1, n)) == -1)
+ {
+ log_error("invalid size+body field\n");
+ return G10ERR_INVALID_PACKET;
+ }
+ if (n+1 > pktlen)
+ {
+ log_error("size+body field is larger than the packet\n");
+ return G10ERR_INVALID_PACKET;
+ }
rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL);
if (rc)
log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc));
-
+
*out = result;
-
+
return rc;
}
-/* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 <x> <y> */
-int ecdsa_qbits_from_Q( int qbits ) {
- if( qbits%8>3 ) {
- log_error(_("ECDSA public key is expected to be in SEC encoding multiple of 8 bits\n"));
- return 0;
- }
- qbits -= qbits%8;
- qbits /= 2;
- return qbits;
+/* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point,
+ i.e. 04 <x> <y> */
+int
+ecdsa_qbits_from_Q (int qbits )
+{
+ if ((qbits%8) > 3)
+ {
+ log_error(_("ECDSA public key is expected to be in SEC encoding "
+ "multiple of 8 bits\n"));
+ return 0;
+ }
+ qbits -= qbits%8;
+ qbits /= 2;
+ return qbits;
}
-
-
-
-
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index d43ab2cba..5df336e55 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -939,40 +939,47 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
}
else
{
- if( k->pubkey_algo != PUBKEY_ALGO_ECDH ) {
- for (i = 0; i < ndata; i++)
- {
- n = pktlen;
- k->data[i] = mpi_read (inp, &n, 0);
- pktlen -= n;
- if (list_mode)
- {
- es_fprintf (listfp, "\tdata: ");
- mpi_print (listfp, k->data[i], mpi_print_mode);
- es_putc ('\n', listfp);
- }
- if (!k->data[i])
- rc = gpg_error (GPG_ERR_INV_PACKET);
- }
- }
- else
+ if (k->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- byte encr_buf[255];
- assert( ndata == 2 );
- n = pktlen; k->data[0] = mpi_read(inp, &n, 0); pktlen -=n;
- rc = iobuf_read_size_body( inp, encr_buf, sizeof(encr_buf), pktlen, k->data+1 );
- if( rc )
- goto leave;
- if( list_mode ) {
- es_fprintf (listfp, "\tdata: ");
- mpi_print(listfp, k->data[0], mpi_print_mode );
- es_putc ('\n', listfp);
- es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1);
- mpi_print(listfp, k->data[1], mpi_print_mode );
- es_putc ('\n', listfp);
- }
- pktlen -= (encr_buf[0]+1);
- }
+ byte encr_buf[255];
+
+ assert (ndata == 2);
+ n = pktlen;
+ k->data[0] = mpi_read (inp, &n, 0);
+ pktlen -= n;
+ rc = iobuf_read_size_body (inp, encr_buf, sizeof(encr_buf),
+ pktlen, k->data+1);
+ if (rc)
+ goto leave;
+
+ if (list_mode)
+ {
+ es_fprintf (listfp, "\tdata: ");
+ mpi_print (listfp, k->data[0], mpi_print_mode );
+ es_putc ('\n', listfp);
+ es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1);
+ mpi_print (listfp, k->data[1], mpi_print_mode );
+ es_putc ('\n', listfp);
+ }
+ pktlen -= (encr_buf[0]+1);
+ }
+ else
+ {
+ for (i = 0; i < ndata; i++)
+ {
+ n = pktlen;
+ k->data[i] = mpi_read (inp, &n, 0);
+ pktlen -= n;
+ if (list_mode)
+ {
+ es_fprintf (listfp, "\tdata: ");
+ mpi_print (listfp, k->data[i], mpi_print_mode);
+ es_putc ('\n', listfp);
+ }
+ if (!k->data[i])
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ }
+ }
}
leave:
@@ -1946,61 +1953,74 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
else
{
/* Fill in public key parameters. */
- if( algorithm != PUBKEY_ALGO_ECDSA && algorithm != PUBKEY_ALGO_ECDH ) {
- for (i = 0; i < npkey; i++)
- {
- n = pktlen;
- pk->pkey[i] = mpi_read (inp, &n, 0);
- pktlen -= n;
- if (list_mode)
- {
- es_fprintf (listfp, "\tpkey[%d]: ", i);
- mpi_print (listfp, pk->pkey[i], mpi_print_mode);
- es_putc ('\n', listfp);
- }
- if (!pk->pkey[i])
- err = gpg_error (GPG_ERR_INV_PACKET);
- }
- }
- else {
- /* note that the code in this function ignores the errors */
- byte name_oid[256];
- err = iobuf_read_size_body( inp, name_oid, sizeof(name_oid), pktlen, pk->pkey+0 );
- if( err )
- goto leave;
- n = name_oid[0];
- if( list_mode )
- es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n",
- n, name_oid[1+n-2], name_oid[1+n-1] );
- pktlen -= (n+1);
- /* set item [1], which corresponds to the public key; these two fields are all we need to uniquely define the key */
- // log_debug("Parsing ecc public key in the public packet, pktlen=%lu\n", pktlen);
- n = pktlen; pk->pkey[1] = mpi_read( inp, &n, 0 ); pktlen -=n;
- if( pk->pkey[1]==NULL )
- err = gpg_error(G10ERR_INVALID_PACKET);
- else if( list_mode ) {
- es_fprintf (listfp, "\tpkey[1]: ");
- mpi_print(listfp, pk->pkey[1], mpi_print_mode);
- es_putc ('\n', listfp);
+ if (algorithm == PUBKEY_ALGO_ECDSA && algorithm == PUBKEY_ALGO_ECDH)
+ {
+ /* FIXME: The code in this function ignores the errors. */
+ byte name_oid[256];
+
+ err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid),
+ pktlen, pk->pkey+0);
+ if (err)
+ goto leave;
+ n = name_oid[0];
+ if (list_mode)
+ es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n",
+ n, name_oid[1+n-2], name_oid[1+n-1]);
+ pktlen -= (n+1);
+ /* Set item [1], which corresponds to the public key; these
+ two fields are all we need to uniquely define the key/ */
+ n = pktlen;
+ pk->pkey[1] = mpi_read( inp, &n, 0 );
+ pktlen -=n;
+ if (!pk->pkey[1])
+ err = gpg_error (GPG_ERR_INV_PACKET);
+ else if (list_mode)
+ {
+ es_fprintf (listfp, "\tpkey[1]: ");
+ mpi_print (listfp, pk->pkey[1], mpi_print_mode);
+ es_putc ('\n', listfp);
}
- /* One more field for ECDH */
- if( algorithm == PUBKEY_ALGO_ECDH ) {
-#define kek_params name_oid
- err = iobuf_read_size_body( inp, kek_params, sizeof(kek_params), pktlen, pk->pkey+2 );
- if( err )
- goto leave;
- n = kek_params[0];
- if( kek_params[1] != 1 ) {
- log_error("invalid ecdh KEK parameters field type in private key: understand type 1, but found 0x%02x\n", kek_params[1]);
- err = gpg_error(G10ERR_INVALID_PACKET);
- goto leave;
- }
- if( list_mode )
- es_fprintf (listfp, "\tpkey[2]: KEK params type=01 hash:%d sym-algo:%d\n", kek_params[1+n-2], kek_params[1+n-1] );
- pktlen -= (n+1);
-#undef kek_params
- }
- }
+ /* One more field for ECDH. */
+ if (algorithm == PUBKEY_ALGO_ECDH)
+ {
+ /* (NAMEOID holds the KEK params.) */
+ err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid),
+ pktlen, pk->pkey+2);
+ if (err)
+ goto leave;
+ n = name_oid[0];
+ if (name_oid[1] != 1)
+ {
+ log_error ("invalid ecdh KEK parameters field type in "
+ "private key: understand type 1, "
+ "but found 0x%02x\n", name_oid[1]);
+ err = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+ if (list_mode)
+ es_fprintf (listfp, "\tpkey[2]: KEK params type=01 "
+ "hash:%d sym-algo:%d\n",
+ name_oid[1+n-2], name_oid[1+n-1]);
+ pktlen -= (n+1);
+ }
+ }
+ else
+ {
+ for (i = 0; i < npkey; i++)
+ {
+ n = pktlen;
+ pk->pkey[i] = mpi_read (inp, &n, 0);
+ pktlen -= n;
+ if (list_mode)
+ {
+ es_fprintf (listfp, "\tpkey[%d]: ", i);
+ mpi_print (listfp, pk->pkey[i], mpi_print_mode);
+ es_putc ('\n', listfp);
+ }
+ if (!pk->pkey[i])
+ err = gpg_error (GPG_ERR_INV_PACKET);
+ }
+ }
if (err)
goto leave;
}
diff --git a/g10/pkglue.c b/g10/pkglue.c
index 9050cc241..f5c85976f 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -1,5 +1,5 @@
/* pkglue.c - public key operations glue code
- * Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -29,7 +29,8 @@
#include "pkglue.h"
#include "main.h"
-
+/* FIXME: Better chnage the fucntion name because mpi_ is used by
+ gcrypt macros. */
gcry_mpi_t
mpi_from_sexp (gcry_sexp_t sexp, const char * item)
{
@@ -45,101 +46,37 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item)
}
-/****************
- * Emulate our old PK interface here - sometime in the future we might
- * change the internal design to directly fit to libgcrypt.
- */
-int
-pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
-{
- gcry_sexp_t s_sig, s_hash, s_skey;
- int rc;
- int gcry_pkalgo = map_pk_openpgp_to_gcry( algo );
-
- /* make a sexp from skey */
- if (gcry_pkalgo == GCRY_PK_DSA)
- {
- rc = gcry_sexp_build (&s_skey, NULL,
- "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
- skey[0], skey[1], skey[2], skey[3], skey[4]);
- }
- else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S)
- {
- rc = gcry_sexp_build (&s_skey, NULL,
- "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
- skey[0], skey[1], skey[2], skey[3], skey[4],
- skey[5]);
- }
- else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E)
- {
- rc = gcry_sexp_build (&s_skey, NULL,
- "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
- skey[0], skey[1], skey[2], skey[3]);
- }
- else if (gcry_pkalgo == GCRY_PK_ECDSA)
- {
- rc = gcry_sexp_build (&s_skey, NULL,
- "(private-key(ecdsa(c%m)(q%m)(d%m)))",
- skey[0], skey[1], skey[2] );
- }
- else
- return GPG_ERR_PUBKEY_ALGO;
-
- if (rc)
- BUG ();
-
- /* put hash into a S-Exp s_hash */
- if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
- BUG ();
-
- rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_skey);
-
- if (rc)
- ;
- else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S)
- data[0] = mpi_from_sexp (s_sig, "s");
- else
- {
- data[0] = mpi_from_sexp (s_sig, "r");
- data[1] = mpi_from_sexp (s_sig, "s");
- }
-
- gcry_sexp_release (s_sig);
- return rc;
-}
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
*/
int
-pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
+pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
{
gcry_sexp_t s_sig, s_hash, s_pkey;
int rc;
- const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo );
+ const int pkalgo = map_pk_openpgp_to_gcry (algo);
- /* make a sexp from pkey */
- if (gcry_pkalgo == GCRY_PK_DSA)
+ /* Make a sexp from pkey. */
+ if (pkalgo == GCRY_PK_DSA)
{
rc = gcry_sexp_build (&s_pkey, NULL,
"(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
pkey[0], pkey[1], pkey[2], pkey[3]);
}
- else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E)
+ else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
{
rc = gcry_sexp_build (&s_pkey, NULL,
"(public-key(elg(p%m)(g%m)(y%m)))",
pkey[0], pkey[1], pkey[2]);
}
- else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S)
+ else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
{
rc = gcry_sexp_build (&s_pkey, NULL,
"(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
}
- else if (gcry_pkalgo == GCRY_PK_ECDSA) /* same as GCRY_PK_ECDH */
+ else if (pkalgo == GCRY_PK_ECDSA) /* Same as GCRY_PK_ECDH */
{
rc = gcry_sexp_build (&s_pkey, NULL,
"(public-key(ecdsa(c%m)(q%m)))", pkey[0], pkey[1]);
@@ -150,13 +87,13 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
if (rc)
BUG (); /* gcry_sexp_build should never fail. */
- /* put hash into a S-Exp s_hash */
+ /* Put hash into a S-Exp s_hash. */
if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
BUG (); /* gcry_sexp_build should never fail. */
/* Put data into a S-Exp s_sig. */
s_sig = NULL;
- if (gcry_pkalgo == GCRY_PK_DSA)
+ if (pkalgo == GCRY_PK_DSA)
{
if (!data[0] || !data[1])
rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -164,7 +101,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
rc = gcry_sexp_build (&s_sig, NULL,
"(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
}
- else if (gcry_pkalgo == GCRY_PK_ECDSA)
+ else if (pkalgo == GCRY_PK_ECDSA)
{
if (!data[0] || !data[1])
rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -172,7 +109,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
rc = gcry_sexp_build (&s_sig, NULL,
"(sig-val(ecdsa(r%m)(s%m)))", data[0], data[1]);
}
- else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E)
+ else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
{
if (!data[0] || !data[1])
rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -180,7 +117,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
rc = gcry_sexp_build (&s_sig, NULL,
"(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
}
- else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S)
+ else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
{
if (!data[0])
rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -207,12 +144,13 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey)
* change the internal design to directly fit to libgcrypt.
*/
int
-pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t * pkey)
+pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+ const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey)
{
gcry_sexp_t s_ciph, s_data, s_pkey;
int rc;
- /* make a sexp from pkey */
+ /* Make a sexp from pkey. */
if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
{
rc = gcry_sexp_build (&s_pkey, NULL,
@@ -227,7 +165,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX
}
else if (algo == PUBKEY_ALGO_ECDH)
{
- return pk_ecdh_encrypt( resarr, pk_fp, data, pkey );
+ return pk_ecdh_encrypt (resarr, pk_fp, data, pkey);
}
else
return GPG_ERR_PUBKEY_ALGO;
@@ -235,11 +173,11 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX
if (rc)
BUG ();
- /* put the data into a simple list */
+ /* Put the data into a simple list. */
if (gcry_sexp_build (&s_data, NULL, "%m", data))
BUG ();
- /* pass it to libgcrypt */
+ /* Pass it to libgcrypt. */
rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
gcry_sexp_release (s_data);
gcry_sexp_release (s_pkey);
@@ -247,9 +185,11 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX
if (rc)
;
else
- { /* add better error handling or make gnupg use S-Exp directly */
+ { /* Add better error handling or make gnupg use S-Exp directly. */
resarr[0] = mpi_from_sexp (s_ciph, "a");
- if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E && algo != PUBKEY_ALGO_ECDH)
+ if (algo != GCRY_PK_RSA
+ && algo != GCRY_PK_RSA_E
+ && algo != PUBKEY_ALGO_ECDH)
resarr[1] = mpi_from_sexp (s_ciph, "b");
}
@@ -257,6 +197,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX
return rc;
}
+
/* Check whether SKEY is a suitable secret key. */
int
pk_check_secret_key (int algo, gcry_mpi_t *skey)
diff --git a/g10/pkglue.h b/g10/pkglue.h
index a1c821dcd..0ceb43f55 100644
--- a/g10/pkglue.h
+++ b/g10/pkglue.h
@@ -1,5 +1,5 @@
/* pkglue.h - public key operations definitions
- * Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -22,21 +22,19 @@
gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item);
-int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash,
- gcry_mpi_t *skey);
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);
-int pk_decrypt (int algo, gcry_mpi_t *result, const byte fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data,
- gcry_mpi_t *skey);
int pk_check_secret_key (int algo, gcry_mpi_t *skey);
-int pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey);
-int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey);
+int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
+ gcry_mpi_t data, gcry_mpi_t * pkey);
+int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN],
+ gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey);
-gcry_mpi_t pk_ecdh_default_params_to_mpi( int qbits );
-byte *pk_ecdh_default_params( int qbits, size_t *sizeout );
+gcry_mpi_t pk_ecdh_default_params_to_mpi (int qbits);
+byte *pk_ecdh_default_params (int qbits, size_t *sizeout);
#endif /*GNUPG_G10_PKGLUE_H*/
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 24411e8a1..ddca41ec4 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -218,68 +218,72 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
log_printhex ("DEK frame:", frame, nframe);
n = 0;
- if( sk->pubkey_algo != PUBKEY_ALGO_ECDH ) {
- if (!card)
- {
- if (n + 7 > nframe)
- {
- err = gpg_error (G10ERR_WRONG_SECKEY);
- goto leave;
- }
- if (frame[n] == 1 && frame[nframe - 1] == 2)
- {
- log_info (_("old encoding of the DEK is not supported\n"));
- err = gpg_error (G10ERR_CIPHER_ALGO);
- goto leave;
- }
- if (frame[n] != 2) /* Something went wrong. */
- {
- err = gpg_error (G10ERR_WRONG_SECKEY);
- goto leave;
- }
- for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */
- ;
- n++; /* Skip the zero byte. */
- }
- }
- else {
- gcry_mpi_t shared_mpi;
- gcry_mpi_t decoded;
-
- /* at the beginning the frame is the bytes of shared point MPI */
-
- err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
- if (err) {
- log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
- goto leave;
- }
+ if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ {
+ gcry_mpi_t shared_mpi;
+ gcry_mpi_t decoded;
+
+ /* At the beginning the frame are the bytes of shared point MPI. */
+ err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
+ if (err)
+ {
+ log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
- err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, shared_mpi, sk->pkey);
- mpi_release( shared_mpi );
- if( err )
- goto leave;
+ err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/,
+ shared_mpi, sk->pkey);
+ mpi_release (shared_mpi);
+ if(err)
+ goto leave;
- /* reuse nframe, which size is sufficient to include the session key */
- err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
- mpi_release( decoded );
- if( err )
- goto leave;
+ /* Reuse NFRAME, which size is sufficient to include the session key. */
+ err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
+ mpi_release (decoded);
+ if (err)
+ goto leave;
- /* Now the frame is the bytes decrypted but padded session key */
+ /* Now the frame are the bytes decrypted but padded session key. */
- /* Allow double padding for the benefit of DEK size concealment.
- * Higher than this is wasteful.
- */
- if( frame[nframe-1] > 8*2 || nframe <= 8 ) {
- err = G10ERR_WRONG_SECKEY; goto leave;
+ /* Allow double padding for the benefit of DEK size concealment.
+ Higher than this is wasteful. */
+ if (frame[nframe-1] > 8*2 || nframe <= 8)
+ {
+ err = gpg_error (GPG_ERR_WRONG_SECKEY);
+ goto leave;
+ }
+ nframe -= frame[nframe-1]; /* Remove padding. */
+ assert (n); /* (used just below) */
+ }
+ else
+ {
+ if (!card)
+ {
+ if (n + 7 > nframe)
+ {
+ err = gpg_error (GPG_ERR_WRONG_SECKEY);
+ goto leave;
+ }
+ if (frame[n] == 1 && frame[nframe - 1] == 2)
+ {
+ log_info (_("old encoding of the DEK is not supported\n"));
+ err = gpg_error (GPG_ERR_CIPHER_ALGO);
+ goto leave;
+ }
+ if (frame[n] != 2) /* Something went wrong. */
+ {
+ err = gpg_error (GPG_ERR_WRONG_SECKEY);
+ goto leave;
+ }
+ for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */
+ ;
+ n++; /* Skip the zero byte. */
+ }
}
- nframe -= frame[nframe-1]; /* remove padding */
- assert( n==0 ); /* used just bellow */
- }
if (n + 4 > nframe)
{
- err = gpg_error (G10ERR_WRONG_SECKEY);
+ err = gpg_error (GPG_ERR_WRONG_SECKEY);
goto leave;
}
diff --git a/g10/seskey.c b/g10/seskey.c
index e50cf5c02..fa6765dc6 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -1,6 +1,6 @@
/* seskey.c - make sesssion keys etc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- * 2006, 2009 Free Software Foundation, Inc.
+ * 2006, 2009, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -76,109 +76,125 @@ make_session_key( DEK *dek )
gcry_mpi_t
encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
{
- size_t nframe = (nbits+7) / 8;
- byte *p;
- byte *frame;
- int i,n;
- u16 csum = 0;
- gcry_mpi_t a;
-
- if( DBG_CIPHER )
- log_debug("encode_session_key: encoding %d byte DEK", dek->keylen);
-
- for( p = dek->key, i=0; i < dek->keylen; i++ )
- csum += *p++;
-
- /* Shortcut for ECDH. It's padding is minimal to simply make the output be a multiple of 8 bytes. */
- if( openpgp_pk_algo == PUBKEY_ALGO_ECDH ) {
- /* pad to 8 byte granulatiry; the padding byte is the number of padded bytes.
- * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x
- * +---- x times ---+
- */
- nframe = ( 1 + dek->keylen + 2 /* the value so far is always odd */ + 7 ) & (~7);
- assert( !(nframe%8) && nframe > 1 + dek->keylen + 2 ); /* alg+key+csum fit and the size is congruent to 8 */
- frame = xmalloc_secure( nframe );
- n = 0;
- frame[n++] = dek->algo;
- memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
- frame[n++] = csum >>8;
- frame[n++] = csum;
- i = nframe - n; /* number padded bytes */
- memset( frame+n, i, i );/* use it as the value of each padded byte */
- assert( n+i == nframe );
-
- if( DBG_CIPHER )
- log_debug("encode_session_key: [%d] %02x %02x %02x ... %02x %02x %02x", nframe, frame[0],frame[1],frame[2], frame[nframe-3],frame[nframe-2],frame[nframe-1]);
-
- if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, nframe, &nframe))
- BUG();
- xfree(frame);
- return a;
+ size_t nframe = (nbits+7) / 8;
+ byte *p;
+ byte *frame;
+ int i,n;
+ u16 csum;
+ gcry_mpi_t a;
+
+ if (DBG_CIPHER)
+ log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
+
+ csum = 0;
+ for (p = dek->key, i=0; i < dek->keylen; i++)
+ csum += *p++;
+
+ /* Shortcut for ECDH. It's padding is minimal to simply make the
+ output be a multiple of 8 bytes. */
+ if (openpgp_pk_algo == PUBKEY_ALGO_ECDH)
+ {
+ /* Pad to 8 byte granulatiry; the padding byte is the number of
+ * padded bytes.
+ *
+ * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x
+ * +---- x times ---+
+ */
+ nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */
+ + 7 ) & (~7));
+
+ /* alg+key+csum fit and the size is congruent to 8. */
+ assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 );
+
+ frame = xmalloc_secure (nframe);
+ n = 0;
+ frame[n++] = dek->algo;
+ memcpy (frame+n, dek->key, dek->keylen);
+ n += dek->keylen;
+ frame[n++] = csum >> 8;
+ frame[n++] = csum;
+ i = nframe - n; /* Number of padded bytes. */
+ memset (frame+n, i, i); /* Use it as the value of each padded byte. */
+ assert (n+i == nframe);
+
+ if (DBG_CIPHER)
+ log_debug ("encode_session_key: "
+ "[%d] %02x %02x %02x ... %02x %02x %02x\n",
+ nframe, frame[0], frame[1], frame[2],
+ frame[nframe-3], frame[nframe-2], frame[nframe-1]);
+
+ if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe))
+ BUG();
+ xfree(frame);
+ return a;
}
-
- /* The current limitation is that we can only use a session key
- * whose length is a multiple of BITS_PER_MPI_LIMB
- * I think we can live with that.
- */
- if( dek->keylen + 7 > nframe || !nframe )
- log_bug("can't encode a %d bit key in a %d bits frame\n",
- dek->keylen*8, nbits );
-
- /* We encode the session key in this way:
- *
- * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
- *
- * (But how can we store the leading 0 - the external representaion
- * of MPIs doesn't allow leading zeroes =:-)
- *
- * RND are non-zero random bytes.
- * A is the cipher algorithm
- * DEK is the encryption key (session key) length k depends on the
- * cipher algorithm (20 is used with blowfish160).
- * CSUM is the 16 bit checksum over the DEK
- */
-
- frame = xmalloc_secure( nframe );
- n = 0;
- frame[n++] = 0;
- frame[n++] = 2;
- i = nframe - 6 - dek->keylen;
- assert( i > 0 );
- p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
- /* Replace zero bytes by new values. */
- for(;;) {
- int j, k;
- byte *pp;
-
- /* count the zero bytes */
- for(j=k=0; j < i; j++ )
- if( !p[j] )
- k++;
- if( !k )
- break; /* okay: no zero bytes */
- k += k/128 + 3; /* better get some more */
- pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
- for(j=0; j < i && k ;) {
- if( !p[j] )
- p[j] = pp[--k];
- if (p[j])
- j++;
+
+ /* The current limitation is that we can only use a session key
+ * whose length is a multiple of BITS_PER_MPI_LIMB
+ * I think we can live with that.
+ */
+ if (dek->keylen + 7 > nframe || !nframe)
+ log_bug ("can't encode a %d bit key in a %d bits frame\n",
+ dek->keylen*8, nbits );
+
+ /* We encode the session key in this way:
+ *
+ * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
+ *
+ * (But how can we store the leading 0 - the external representaion
+ * of MPIs doesn't allow leading zeroes =:-)
+ *
+ * RND are non-zero random bytes.
+ * A is the cipher algorithm
+ * DEK is the encryption key (session key) length k depends on the
+ * cipher algorithm (20 is used with blowfish160).
+ * CSUM is the 16 bit checksum over the DEK
+ */
+
+ frame = xmalloc_secure( nframe );
+ n = 0;
+ frame[n++] = 0;
+ frame[n++] = 2;
+ i = nframe - 6 - dek->keylen;
+ assert( i > 0 );
+ p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
+ /* Replace zero bytes by new values. */
+ for (;;)
+ {
+ int j, k;
+ byte *pp;
+
+ /* Count the zero bytes. */
+ for (j=k=0; j < i; j++ )
+ if (!p[j])
+ k++;
+ if (!k)
+ break; /* Okay: no zero bytes. */
+ k += k/128 + 3; /* Better get some more. */
+ pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
+ for (j=0; j < i && k ;)
+ {
+ if (!p[j])
+ p[j] = pp[--k];
+ if (p[j])
+ j++;
}
- xfree(pp);
+ xfree (pp);
}
- memcpy( frame+n, p, i );
- xfree(p);
- n += i;
- frame[n++] = 0;
- frame[n++] = dek->algo;
- memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
- frame[n++] = csum >>8;
- frame[n++] = csum;
- assert( n == nframe );
- if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
- BUG();
- xfree(frame);
- return a;
+ memcpy (frame+n, p, i);
+ xfree (p);
+ n += i;
+ frame[n++] = 0;
+ frame[n++] = dek->algo;
+ memcpy (frame+n, dek->key, dek->keylen );
+ n += dek->keylen;
+ frame[n++] = csum >>8;
+ frame[n++] = csum;
+ assert (n == nframe);
+ if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
+ BUG();
+ xfree (frame);
+ return a;
}
@@ -192,8 +208,8 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
gcry_mpi_t a;
if( len + asnlen + 4 > nframe )
- log_bug("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
- (int)(len*8), (int)nbits, algo);
+ log_bug ("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
+ (int)(len*8), (int)nbits, algo);
/* We encode the MD in this way:
*
@@ -240,26 +256,27 @@ gcry_mpi_t
encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
{
gcry_mpi_t frame;
- int gcry_pkalgo;
+ int pkalgo;
assert (hash_algo);
assert (pk);
- gcry_pkalgo = map_pk_openpgp_to_gcry( pk->pubkey_algo );
+ pkalgo = map_pk_openpgp_to_gcry (pk->pubkey_algo);
- if (gcry_pkalgo == GCRY_PK_DSA || gcry_pkalgo == GCRY_PK_ECDSA )
+ if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA)
{
- /* It's a DSA signature, so find out the size of q. */
+ /* It's a DSA signature, so find out the size of q. */
size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]);
- /* pkey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 <x> <y> */
- if( gcry_pkalgo==GCRY_PK_ECDSA )
- qbytes = ecdsa_qbits_from_Q( qbytes );
-
+ /* pkey[1] is Q for ECDSA, which is an uncompressed point,
+ i.e. 04 <x> <y> */
+ if (pkalgo == GCRY_PK_ECDSA)
+ qbytes = ecdsa_qbits_from_Q (qbytes);
+
/* Make sure it is a multiple of 8 bits. */
-
- if(qbytes%8)
+
+ if (qbytes%8)
{
log_error(_("DSA requires the hash length to be a"
" multiple of 8 bits\n"));
@@ -275,30 +292,38 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
if (qbytes < 160)
{
log_error (_("%s key %s uses an unsafe (%zu bit) hash\n"),
- gcry_pk_algo_name( gcry_pkalgo ),
- keystr_from_pk (pk), qbytes);
+ gcry_pk_algo_name (pkalgo), keystr_from_pk (pk), qbytes);
return NULL;
}
-
+
qbytes /= 8;
/* Check if we're too short. Too long is safe as we'll
- automatically left-truncate. */
- /* This checks 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 will never pass for ECDSA 521 anyway as the only hash that intended to match it is SHA 512, but 512 < 521 ).
- */
- if (gcry_md_get_algo_dlen (hash_algo) < ((gcry_pkalgo==GCRY_PK_ECDSA && qbytes>(521)/8) ? 512/8 : qbytes) )
+ automatically left-truncate.
+
+ FIXME: Check against FIPS.
+ This checks 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 will
+ never pass for ECDSA 521 anyway as the only hash that
+ intended to match it is SHA 512, but 512 < 521). */
+ if (gcry_md_get_algo_dlen (hash_algo)
+ < ((pkalgo == GCRY_PK_ECDSA && qbytes > (521)/8) ? 512/8 : qbytes))
{
- log_error (_("%s key %s requires a %zu bit or larger hash, used hash-algo=%d\n"),
- gcry_pk_algo_name( gcry_pkalgo ),
- keystr_from_pk(pk), qbytes*8, hash_algo);
+ log_error (_("%s key %s requires a %zu bit or larger hash "
+ "(hash is %s\n"),
+ gcry_pk_algo_name (pkalgo),
+ keystr_from_pk(pk), qbytes*8,
+ gcry_md_algo_name (hash_algo));
return NULL;
}
- /* Note that in case of ECDSA 521 hash is always smaller than the key size */
+ /* Note that in case of ECDSA 521 hash is always smaller than
+ the key size. */
if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG,
- gcry_md_read (md, hash_algo), gcry_md_get_algo_dlen (hash_algo), &qbytes))
+ gcry_md_read (md, hash_algo),
+ gcry_md_get_algo_dlen (hash_algo), &qbytes))
BUG();
}
else
diff --git a/g10/sign.c b/g10/sign.c
index ccf796446..30dc66d5f 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -436,14 +436,15 @@ hash_for (PKT_public_key *pk)
{
return recipient_digest_algo;
}
- else if(pk->pubkey_algo==PUBKEY_ALGO_DSA || pk->pubkey_algo==PUBKEY_ALGO_ECDSA )
+ else if (pk->pubkey_algo == PUBKEY_ALGO_DSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
{
unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]);
- if( pk->pubkey_algo==PUBKEY_ALGO_ECDSA )
- qbytes = ecdsa_qbits_from_Q(qbytes);
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
+ qbytes = ecdsa_qbits_from_Q (qbytes);
qbytes = qbytes/8;
-
+
/* It's a DSA key, so find a hash that is the same size as q or
larger. If q is 160, assume it is an old DSA key and use a
160-bit hash unless --enable-dsa2 is set, in which case act
@@ -924,12 +925,14 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
{
- if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA )
+ if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA
+ || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
{
- int temp_hashlen = gcry_mpi_get_nbits(sk_rover->pk->pkey[1]);
+ int temp_hashlen = (gcry_mpi_get_nbits
+ (sk_rover->pk->pkey[1]));
- if( sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA )
- temp_hashlen = ecdsa_qbits_from_Q( temp_hashlen );
+ if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
+ temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen);
temp_hashlen = (temp_hashlen+7)/8;
/* Pick a hash that is large enough for our
@@ -1482,13 +1485,14 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
if(opt.cert_digest_algo)
digest_algo=opt.cert_digest_algo;
- else if(pksk->pubkey_algo==PUBKEY_ALGO_RSA
+ else if(pksk->pubkey_algo == PUBKEY_ALGO_RSA
&& pk->version<4 && sigversion<4)
digest_algo = DIGEST_ALGO_MD5;
- else if(pksk->pubkey_algo==PUBKEY_ALGO_DSA)
- digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8 );
- else if(pksk->pubkey_algo==PUBKEY_ALGO_ECDSA )
- digest_algo = match_dsa_hash (ecdsa_qbits_from_Q( gcry_mpi_get_nbits (pksk->pkey[1]) ) / 8);
+ else if(pksk->pubkey_algo == PUBKEY_ALGO_DSA)
+ digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
+ else if(pksk->pubkey_algo == PUBKEY_ALGO_ECDSA )
+ digest_algo = match_dsa_hash (ecdsa_qbits_from_Q
+ (gcry_mpi_get_nbits (pksk->pkey[1]))/8);
else
digest_algo = DIGEST_ALGO_SHA1;
}
diff --git a/g10/verify-stubs.c b/g10/verify-stubs.c
index d1f0aa105..c4c657b9f 100644
--- a/g10/verify-stubs.c
+++ b/g10/verify-stubs.c
@@ -1,6 +1,5 @@
/* To satisfy the linker for the gpgv target
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
- * 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -25,6 +24,8 @@
#include "main.h"
int
-pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits) {
- return GPG_ERR_NOT_IMPLEMENTED;
+pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, int keygen_flags,
+ char **cache_nonce_addr, unsigned nbits)
+{
+ return GPG_ERR_NOT_IMPLEMENTED;
}
diff --git a/g13/utils.c b/g13/utils.c
index 1ea7f3275..4b374df10 100644
--- a/g13/utils.c
+++ b/g13/utils.c
@@ -176,7 +176,5 @@ next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length)
}
return NULL;
-}
-
-
+}
diff --git a/include/ChangeLog b/include/ChangeLog
index 339800f37..7c1b372ab 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,9 @@
+2011-01-21 Werner Koch <[email protected]>
+
+ * cipher.h (GCRY_PK_USAGE_CERT): Remove comaptibility macros
+ because we now require libgcrypt 1.4.6.
+ (GCRY_PK_ECDH): Add replacement.
+
2009-08-20 Daiki Ueno <[email protected]> (wk)
* cipher.h (struct DEK): Add field S2K_CACHEID.
diff --git a/include/cipher.h b/include/cipher.h
index 65cd59e76..03d38da5b 100644
--- a/include/cipher.h
+++ b/include/cipher.h
@@ -1,6 +1,6 @@
/* cipher.h - Definitions for OpenPGP
* Copyright (C) 1998, 1999, 2000, 2001, 2006,
- * 2007 Free Software Foundation, Inc.
+ * 2007, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,10 +23,8 @@
#include <gcrypt.h>
/* Macros for compatibility with older libgcrypt versions. */
-#ifndef GCRY_PK_USAGE_CERT
-# define GCRY_PK_USAGE_CERT 4
-# define GCRY_PK_USAGE_AUTH 8
-# define GCRY_PK_USAGE_UNKN 128
+#ifndef HAVE_GCRY_PK_ECDSA
+# define GCRY_PK_ECDH 302
#endif
@@ -56,8 +54,8 @@
#define PUBKEY_ALGO_RSA_S /* 3 */ GCRY_PK_RSA_S /* RSA sign only. */
#define PUBKEY_ALGO_ELGAMAL_E /* 16 */ GCRY_PK_ELG_E /* Elgamal encr only */
#define PUBKEY_ALGO_DSA /* 17 */ GCRY_PK_DSA
-#define PUBKEY_ALGO_ECDH 18 /* corresponds to GCRY_PK_ECDH ECC DH; encrypt only */
-#define PUBKEY_ALGO_ECDSA 19 /* corresponds to GCRY_PK_ECDSA ECC DSA; sign only */
+#define PUBKEY_ALGO_ECDH 18
+#define PUBKEY_ALGO_ECDSA 19
#define PUBKEY_ALGO_ELGAMAL /* 20 */ GCRY_PK_ELG /* Elgamal encr+sign */
#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */
diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c
index 6c9410e05..f1de685cf 100644
--- a/kbx/keybox-openpgp.c
+++ b/kbx/keybox-openpgp.c
@@ -245,6 +245,7 @@ parse_key (const unsigned char *data, size_t datalen,
break;
case 18: /* ECDH */
npkey = 3;
+ break;
case 19: /* ECDSA */
npkey = 2;
break;