diff --git a/ChangeLog b/ChangeLog index 656fe7212..287e4d1c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-01-21 Werner Koch + + * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. + (HAVE_GCRY_PK_ECDH): Add new test. + 2011-01-03 Werner Koch * 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 + + * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. + 2010-12-02 Werner Koch * 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 #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 ], + [ 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= 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= 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= 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= 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; - } + { + 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) ); + 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 ); - 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) + 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 ) + 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); + 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_scan ( &result, GCRYMPI_FMT_USG, data_buf, 1+data_buf[0], NULL); /* (byte)size + aeswrap of DEK */ - xfree( data_buf ); - 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"); + 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; - } + if (rc) + { + log_error ("ecdh failed in gcry_cipher_decrypt: %s\n", + gpg_strerror (rc)); + xfree (data_buf); + return rc; + } - data_buf_size-=8; + data_buf_size -= 8; - if( DBG_CIPHER ) - log_printhex ("ecdh decrypted to :", in, data_buf_size ); + 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; - //} + /* 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 */ - gcry_sexp_release (s_ciph); - resarr[0] = mpi_from_sexp (s_ciph, "b"); /* ephemeral public key */ + /* ... and get the shared point/ */ + gcry_mpi_t shared; - if( DBG_CIPHER ) { + shared = mpi_from_sexp (s_ciph, "a"); + gcry_sexp_release (s_ciph); + /* Ephemeral public key. */ + resarr[0] = mpi_from_sexp (s_ciph, "b"); + + 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 . */ +#warning wk: check these changes. #include #include #include @@ -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 */ -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 */ +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; + 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; + } - /* 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; + 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; + + /* 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 = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + nframe -= frame[nframe-1]; /* Remove padding. */ + assert (n); /* (used just below) */ } - - 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; - - /* Now the frame is 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; + 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; + 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); - 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++; - 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); - /* 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; + 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 + */ - /* 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++; + 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 */ - 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 */ + 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 + + * 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 (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 /* 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;