From: Eli Zaretskii <eliz@gnu.org>
To: emacs-devel@gnu.org
Subject: Re: libnettle/libhogweed WIP (was: request to reconsider libnettle/libhogweed)
Date: Thu, 16 Mar 2017 17:28:20 +0200 [thread overview]
Message-ID: <83y3w5z1ez.fsf@gnu.org> (raw)
In-Reply-To: <87shmeb5ln.fsf_-_@lifelogs.com> (message from Ted Zlatanov on Wed, 15 Mar 2017 17:19:32 -0400)
> From: Ted Zlatanov <tzz@lifelogs.com>
> Date: Wed, 15 Mar 2017 17:19:32 -0400
>
> I did some work, at least to shut up the warnings, but it's far from
> ready. I pushed it into the branch scratch/tzz/nettle for now. If you
> could take a look, that would be very helpful.
I took a look, comments below.
> * maybe there's a better way than using the NETTLE_STRING_EQUAL_UNIBYTE
> macro to compare Emacs and C strings?
I think this entire issue should be rethought, see the comments below.
> * several times I've forced casts to shut up warnings, and generally
> could use some help converting between C bytes and the ELisp strings
If you agree with my comments below, most, if not all, of this issue
should go away.
> * data is not wiped after use
I'm not an expert, but AFAIU this is a serious flaw in
security-related software. Should this be optional (as it probably
has non-negligible run-time costs)?
> * it compiles but doesn't link: "error adding symbols: DSO missing from
> command line" which I hope is something trivial
Did the -lhogweed -lnettle switches appear on the link command line?
Here are some comments to the patch:
First, some general observations:
. the patch is missing additions to the manual and NEWS
. support for dynamic loading on MS-Windows should be added
. did you consider exposing this functionality through corresponding
GnuTLS functions?
Specific comments follow:
> + # Windows loads libnettle dynamically
> + if test "${opsys}" = "mingw32"; then
> + LIBNETTLE_LIBS=
> + else
> + CFLAGS="$CFLAGS $LIBNETTLE_CFLAGS"
> + LIBS="$LIBNETTLE_LIBS $LIBS"
> + fi
CFLAGS should be set for the Windows build as well. Only LIBS should
not be added.
> diff --git a/lisp/nettle.el b/lisp/nettle.el
> new file mode 100644
> index 0000000000..6f49c3f031
> --- /dev/null
> +++ b/lisp/nettle.el
> @@ -0,0 +1,335 @@
> +;;; nettle.el --- Interface to libnettle/libhogweed -*- lexical-binding: t; -*-
Actually, this does not seem to be an interface at all. What you have
here are defcustom that seems not to be used anywhere, a bunch of
diagnostic functions useful for debugging, and tests that should be
moved elsewhere anyway. Do we really need this file?
> +;; Copyright (C) 2013 Teodor Zlatanov
This should cite the FSF as the copyright holder, I think.
> @@ -1369,6 +1373,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
> globals_of_kqueue ();
> #endif
> +#ifdef HAVE_NETTLE
> + syms_of_nettle ();
> +#endif
syms_of_nettle should be called only if !initialized.
> +#ifdef HAVE_NETTLE
> +
> +#include "nettle.h"
> +
> +DEFUN ("nettle-available-p", Fnettle_available_p, Snettle_available_p, 0, 0, 0,
> + doc: /* Return t if Nettle is available in this instance of Emacs.
> +
> +The Nettle integration binds Emacs with libnettle and libhogweed.
> +See http://www.lysator.liu.se/~nisse/nettle for more on Nettle. */)
> + (void)
> +{
> + return Qt;
> +}
This function should be outside of the "#ifdef HAVE_NETTLE"
conditional, otherwise it will not be available in an Emacs built
without the library, and Lisp programs will need to use fboundp
instead, which all but defeats the purpose of the function.
> +DEFUN ("nettle-hash", Fnettle_hash, Snettle_hash, 2, 2, 0,
> + doc: /* Hash INPUT string with HASH-METHOD into a unibyte string.
Here and elsewhere, the doc string should explicitly tell that INPUT
must be a unibyte string.
A design question: would it make sense to support vectors as INPUT,
here and in the rest of the functions?
Another design question: should be support buffer regions, instead of
strings, as input to these functions? The way your code is written,
Lisp programs must always cons a string from buffer text, before they
invoke these functions. This could be gratuitous cost in some use
cases.
> + (Lisp_Object input, Lisp_Object hash_method)
> +{
> + Lisp_Object ret = Qnil;
> +
> + CHECK_STRING (input);
> + CHECK_STRING (hash_method);
> +
> + for (int i = 0; NULL != nettle_hashes[i]; i++)
> + {
> + if (NETTLE_STRING_EQUAL_UNIBYTE (hash_method, nettle_hashes[i]->name))
I don't think it's a good idea to use strings for methods and other
such fixed parameters in your patch. We usually use symbols for that.
The advantage of symbols is that you can test equality with EQ,
instead of the costly NETTLE_STRING_EQUAL_UNIBYTE, or any equivalent
code which compares strings.
> + const struct nettle_hash *alg = nettle_hashes[i];
> + unsigned int length = alg->digest_size;
> + void *ctx = xzalloc (alg->context_size);
> + uint8_t *digest;
> + ctx = xzalloc (alg->context_size);
> + alg->init (ctx);
> + alg->update (ctx, SCHARS (input), SDATA (input));
> +
> + digest = xzalloc (length);
> + alg->digest (ctx, length, digest);
> +
> + ret = make_unibyte_string ((const char*) digest, length);
> +
> + xfree (digest);
> + xfree (ctx);
Here and elsewhere, the size of the result is known in advance, so I
would avoid allocating a scratch buffer and then copying its data
(inside make_unibyte_string) into a newly-allocated string. Instead,
use make_uninit_string, and then pass its string data pointer to the
algorithm that produces the digest.
> + uint8_t *digest;
^^^^^^^
Why not 'unsigned char'?
> +DEFUN ("nettle-pbkdf2", Fnettle_pbkdf2, Snettle_pbkdf2, 5, 5, 0,
> + doc: /* Make PBKDF2 of HASH-LENGTH from KEY with HASH-METHOD using ITERATIONS and SALT.
> +
> +The PBKDF2 data is stored in a unibyte string according to RFC 2898.
> +The list of hash-methods can be obtained with `nettle-hashes`.
> +The `sha1' and `sha256' hashing methods are most common and only supported now. */)
This doc string doesn't document the ITERATIONS and SALT arguments.
> +DEFUN ("nettle-rsa-verify", Fnettle_rsa_verify, Snettle_rsa_verify, 4, 4, 0,
> + doc: /* Verify the RSA SIGNATURE of DATA with PUBLIC-KEY and HASH-METHOD.
> +
> +The list of hash-methods can be obtained with `nettle-hashes`.
> +Only the `md5', `sha1', `sha256', and `sha512' hashing methods are supported. */)
This doc string doesn't describe some of its argument, and doesn't
tell their data types.
> +DEFUN ("nettle-crypt", Fnettle_crypt, Snettle_crypt, 6, 6, 0,
> + doc: /* Encrypt or decrypt INPUT in CRYPT-MODE with KEY, CIPHER, CIPHER-MODE, and IV.
> +
> +The INPUT will be zero-padded to be a multiple of the cipher's block size.
> +
> +The KEY will be zero-padded to the cipher's key size and will be
> +trimmed if it exceeds that key size.
> +
> +The list of ciphers can be obtained with `nettle-ciphers`.
> +The list of cipher modes can be obtained with `nettle-cipher-modes`.
> +The `aes256' cipher method is probably best for general use.
> +The `twofish256' cipher method may be better if you want to avoid NIST ciphers. */)
This doesn't document the argument IV, and doesn't tell the data types
of the arguments.
> + mode = CAR_SAFE (Fmember (cipher_mode, Fnettle_cipher_modes ()));
Wouldn't it be less expensive to access the data on the C level,
without consing a list?
> + /* Increment input_length to the next multiple of block_size. */
> + if (0 != alg->block_size)
> + {
> + while (0 != (input_length % alg->block_size))
> + {
> + input_length++;
> + }
> + }
I think there are more efficient ways of doing this, which don't need
an explicit loop.
> + dest = xzalloc (input_length);
> + memcpy (dest, SDATA (input), SCHARS (input));
> + // message("Dest buffer: '%s' and size is %d", dest, input_length);
I don't understand why you copy the data here, instead of passing the
algorithm a pointer to the original string's data.
> + key_hold = xzalloc (alg->key_size);
> + memcpy (key_hold, SDATA (key), min (alg->key_size, SCHARS (key)));
Likewise here. In addition, since you are using 'min', shouldn't we
signal an error if KEY is too long?
> + if (0 == NETTLE_STRING_EQUAL_UNIBYTE (mode, "CBC"))
> + {
> + if (decrypt)
> + {
> + cbc_decrypt (ctx, alg->decrypt,
> + alg->block_size, iv_hold,
> + input_length, dest, dest);
> + }
> + else
> + {
> + cbc_encrypt (ctx, alg->encrypt,
> + alg->block_size, iv_hold,
> + input_length, dest, dest);
> + }
> + }
> + else if (ctr_mode)
> + {
> + ctr_crypt (ctx, alg->encrypt,
> + alg->block_size, iv_hold,
> + input_length, dest, dest);
> + }
> + else
> + {
> + error ("Unexpected error: Nettle cipher mode %s was not found", SDATA (mode));
> + }
> +
> + // message("-> produced (%d) '%s'", input_length, dest);
> + ret = make_unibyte_string ((const char*) dest, input_length);
Once again, since the length is known in advance, producing output
into an allocated buffer and then creating a Lisp string by copying
that buffer is wasteful. It is better to produce output directly into
a string's data.
Thanks again for working on this.
next prev parent reply other threads:[~2017-03-16 15:28 UTC|newest]
Thread overview: 128+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-20 10:00 How to ship native modules? Elias Mårtenson
2017-02-20 15:27 ` Eli Zaretskii
2017-02-20 16:01 ` Elias Mårtenson
2017-02-20 16:30 ` Eli Zaretskii
2017-02-21 2:48 ` Elias Mårtenson
2017-02-21 3:41 ` Eli Zaretskii
2017-02-21 4:13 ` Elias Mårtenson
2017-02-21 16:48 ` Eli Zaretskii
2017-02-21 20:06 ` John Wiegley
2017-02-21 14:44 ` Stefan Monnier
[not found] ` <CADtN0WLjNcFRLCsJNZX+XfqOcq+veTaoGkwHQCV9bjvuQoEORA@mail.gmail.com>
2017-02-21 15:48 ` Elias Mårtenson
2017-02-21 17:14 ` Stefan Monnier
2017-02-21 16:59 ` Eli Zaretskii
2017-03-02 14:59 ` request to reconsider libnettle/libhogweed (was: How to ship native modules?) Ted Zlatanov
2017-03-02 15:19 ` request to reconsider libnettle/libhogweed Stefan Monnier
2017-03-02 15:55 ` request to reconsider libnettle/libhogweed (was: How to ship native modules?) Eli Zaretskii
2017-03-15 21:19 ` libnettle/libhogweed WIP (was: request to reconsider libnettle/libhogweed) Ted Zlatanov
2017-03-16 15:28 ` Eli Zaretskii [this message]
2017-03-17 22:46 ` libnettle/libhogweed WIP Ted Zlatanov
2017-03-18 8:12 ` Eli Zaretskii
2017-03-20 18:45 ` Ted Zlatanov
2017-04-11 20:05 ` Ted Zlatanov
2017-04-14 20:48 ` Ted Zlatanov
2017-04-15 9:32 ` Eli Zaretskii
2017-04-15 14:27 ` Ted Zlatanov
2017-04-15 14:55 ` Eli Zaretskii
2017-04-16 2:39 ` Ted Zlatanov
2017-04-16 6:25 ` Eli Zaretskii
2017-04-16 6:51 ` Eli Zaretskii
2017-04-17 16:23 ` Ted Zlatanov
2017-04-17 16:34 ` Eli Zaretskii
2017-04-17 16:55 ` Ted Zlatanov
2017-04-17 17:11 ` Eli Zaretskii
2017-04-17 17:34 ` Ted Zlatanov
2017-04-17 17:46 ` Ted Zlatanov
2017-04-17 18:11 ` Eli Zaretskii
2017-04-17 20:50 ` Ted Zlatanov
2017-04-17 21:19 ` Noam Postavsky
2017-04-17 23:29 ` Ted Zlatanov
2017-04-19 2:08 ` Ted Zlatanov
2017-04-19 2:42 ` Noam Postavsky
2017-04-19 15:24 ` Davis Herring
2017-04-19 15:45 ` Eli Zaretskii
2017-04-20 17:24 ` Ted Zlatanov
2017-04-20 19:38 ` Eli Zaretskii
2017-04-20 20:24 ` Ted Zlatanov
2017-04-20 20:42 ` Lars Ingebrigtsen
2017-04-20 21:54 ` Ted Zlatanov
2017-04-21 6:21 ` Eli Zaretskii
2017-04-21 18:45 ` Lars Ingebrigtsen
2017-04-21 19:15 ` Eli Zaretskii
2017-04-21 6:14 ` Eli Zaretskii
2017-05-15 21:55 ` Ted Zlatanov
2017-05-16 22:19 ` Ted Zlatanov
2017-05-17 16:22 ` Eli Zaretskii
2017-05-17 20:05 ` Ted Zlatanov
2017-05-31 18:17 ` Ted Zlatanov
2017-06-03 7:23 ` Eli Zaretskii
2017-06-03 9:00 ` Andreas Schwab
2017-06-03 10:01 ` Eli Zaretskii
2017-06-03 10:09 ` Andreas Schwab
2017-06-03 10:47 ` Eli Zaretskii
2017-06-27 22:58 ` Ted Zlatanov
2017-06-28 16:54 ` Eli Zaretskii
2017-06-28 19:44 ` Ted Zlatanov
2017-07-13 18:35 ` Ted Zlatanov
2017-07-14 15:10 ` Ted Zlatanov
2017-07-14 19:04 ` Eli Zaretskii
2017-07-14 19:43 ` Ted Zlatanov
2017-07-14 20:04 ` Eli Zaretskii
2017-07-15 18:30 ` Ted Zlatanov
2017-07-15 9:15 ` Eli Zaretskii
2017-07-15 18:40 ` Ted Zlatanov
2017-07-15 19:12 ` Eli Zaretskii
2017-07-22 9:10 ` Eli Zaretskii
2017-07-26 6:58 ` Ted Zlatanov
2017-07-26 14:52 ` Eli Zaretskii
2017-07-26 15:34 ` Ted Zlatanov
2017-07-26 15:49 ` Eli Zaretskii
2017-07-26 16:08 ` Ted Zlatanov
2017-07-26 18:51 ` Eli Zaretskii
2017-07-26 20:48 ` Ted Zlatanov
2017-07-27 0:19 ` Paul Eggert
2017-07-27 2:34 ` Eli Zaretskii
2017-07-27 4:36 ` Paul Eggert
2017-07-27 15:56 ` Ted Zlatanov
2017-08-03 19:52 ` Ted Zlatanov
2017-08-03 8:02 ` Paul Eggert
2017-08-03 16:49 ` Eli Zaretskii
2017-04-18 17:44 ` Ted Zlatanov
2017-04-19 12:22 ` Stefan Monnier
2017-04-19 13:38 ` Ted Zlatanov
2017-04-19 14:16 ` Lars Ingebrigtsen
2017-04-19 14:48 ` Stefan Monnier
2017-04-19 14:41 ` Eli Zaretskii
2017-04-19 14:54 ` Stefan Monnier
2017-04-19 15:31 ` Eli Zaretskii
2017-04-19 15:48 ` Ted Zlatanov
2017-04-19 16:49 ` Lars Ingebrigtsen
2017-04-19 17:24 ` Eli Zaretskii
2017-04-19 19:53 ` Stefan Monnier
2017-04-20 2:30 ` Eli Zaretskii
2017-04-20 3:36 ` Stefan Monnier
2017-04-20 15:46 ` Eli Zaretskii
2017-04-20 15:59 ` Lars Ingebrigtsen
2017-04-20 16:24 ` Eli Zaretskii
2017-04-20 17:25 ` Stefan Monnier
2017-04-20 19:40 ` Lars Ingebrigtsen
2017-04-20 20:31 ` Eli Zaretskii
2017-04-20 19:58 ` Eli Zaretskii
2017-04-20 20:36 ` Eli Zaretskii
2017-04-20 17:14 ` Stefan Monnier
2017-04-20 19:29 ` Eli Zaretskii
2017-04-19 19:49 ` Stefan Monnier
2017-04-17 16:00 ` rename STRING_SET_CHARS to STRING_SET_SIZE (was: libnettle/libhogweed WIP) Ted Zlatanov
2017-04-17 16:24 ` rename STRING_SET_CHARS to STRING_SET_SIZE Eli Zaretskii
2017-04-17 16:29 ` Stefan Monnier
2017-04-17 16:34 ` Ted Zlatanov
2017-04-16 3:37 ` libnettle/libhogweed WIP Stefan Monnier
2017-04-16 6:19 ` Eli Zaretskii
2017-04-16 13:20 ` Stefan Monnier
2017-04-16 7:47 ` Toon Claes
2017-03-02 17:58 ` request to reconsider libnettle/libhogweed Paul Eggert
2017-03-02 18:33 ` Ted Zlatanov
2017-02-20 15:33 ` How to ship native modules? Aurélien Aptel
2017-02-21 4:50 ` Andreas Politz
2017-02-21 5:12 ` Elias Mårtenson
2017-02-21 5:23 ` Andreas Politz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=83y3w5z1ez.fsf@gnu.org \
--to=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.