* GNU Emacs-libnettle-libhogweed integration patch v1
@ 2013-10-06 9:15 Ted Zlatanov
2013-10-06 9:58 ` bignum support in Emacs with libgmp (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
` (2 more replies)
0 siblings, 3 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-06 9:15 UTC (permalink / raw)
To: emacs-devel; +Cc: nettle-bugs
[-- Attachment #1: Type: text/plain, Size: 911 bytes --]
This is the first cut of the Nettle integration for your review.
Notes:
The tests are inlined for convenience but will be in a separate file
later.
This patch implements, with tests:
- meta info about Nettle's exported hashes and ciphers
- all the hashing functions exported by Nettle
- HMAC keyed hashes with all the hashing functions above
- encrypt/decrypt with all the ciphers exported by Nettle in ECB, CBC, and CTR modes
- PBKDF2 with md5, sha1, and sha256 hashing (the generic version is not
ready, and only sha1 is explicitly tested; the commented-out code will
be rewritten soon)
Not done yet:
- RSA verify data signature: code looks OK; test cases NOT READY
- RSA verify digest signature; RSA sign data and sign digest
- DSA
- ECC
- GCM cipher mode
- Yarrow randomness
- PBKDF2 testing of at least md5 and sha256 hashing
I would appreciate any comments at this early stage.
Ted
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: nettle.patch --]
[-- Type: text/x-diff, Size: 67258 bytes --]
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: tzz@lifelogs.com-20131006085733-og65np14e5z1m3f4
# target_branch: bzr+ssh://tzz@bzr.savannah.gnu.org/emacs/trunk/
# testament_sha1: ef8ed3601dbb5399866cdbd6ac3403ff307c237e
# timestamp: 2013-10-06 04:58:53 -0400
# base_revision_id: dgutov@yandex.ru-20131006012151-wprswhei2ipqvr0c
#
# Begin patch
=== modified file 'configure.ac'
--- configure.ac 2013-09-25 03:44:34 +0000
+++ configure.ac 2013-10-06 08:57:33 +0000
@@ -236,6 +236,7 @@
OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support])
OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
+OPTION_DEFAULT_ON([nettle],[don't use -lhogweed (libnettle) for cryptographic support])
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
@@ -2443,6 +2444,25 @@
AC_SUBST(LIBGNUTLS_LIBS)
AC_SUBST(LIBGNUTLS_CFLAGS)
+HAVE_NETTLE=no
+if test "${with_nettle}" = "yes" ; then
+ PKG_CHECK_MODULES([LIBNETTLE], [hogweed >= 2.7], HAVE_NETTLE=yes, HAVE_NETTLE=no)
+ if test "${HAVE_NETTLE}" = "yes"; then
+ AC_DEFINE(HAVE_NETTLE, 1, [Define if using libnettle+libhogweed.])
+ fi
+
+ # Windows loads libnettle dynamically
+ if test "${opsys}" = "mingw32"; then
+ LIBNETTLE_LIBS=
+ else
+ CFLAGS="$CFLAGS $LIBNETTLE_CFLAGS"
+ LIBS="$LIBNETTLE_LIBS $LIBS"
+ fi
+fi
+
+AC_SUBST(LIBNETTLE_LIBS)
+AC_SUBST(LIBNETTLE_CFLAGS)
+
NOTIFY_OBJ=
NOTIFY_SUMMARY=no
@@ -4934,6 +4954,7 @@
echo " Does Emacs use access control lists? ${acl_summary}"
echo " Does Emacs use -lselinux? ${HAVE_LIBSELINUX}"
echo " Does Emacs use -lgnutls? ${HAVE_GNUTLS}"
+echo " Does Emacs use -lhogweed (libnettle)? ${HAVE_NETTLE}"
echo " Does Emacs use -lxml2? ${HAVE_LIBXML2}"
echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}"
=== added file 'lisp/nettle.el'
--- lisp/nettle.el 1970-01-01 00:00:00 +0000
+++ lisp/nettle.el 2013-10-06 08:57:33 +0000
@@ -0,0 +1,335 @@
+;;; nettle.el --- Interface to libnettle/libhogweed -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2013 Teodor Zlatanov
+
+;; Author: Teodor Zlatanov <tzz@lifelogs.com>
+;; Keywords: data
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides basic functions to interface with libnettle and libhogweed
+;; through nettle.c
+
+;; Test with ./emacs --batch --load "/path/to/nettle.el" -f ert-run-tests-batch
+
+;;; Code:
+
+(require 'cl)
+(require 'ert)
+(require 'hex-util)
+
+;;;###autoload
+(defcustom nettle-payloads-store-secrets nil
+ "Whether the Nettle interface should store secrets in the payloads.
+The secrets are: the key, the IV, and the original input.
+Set this to t if you're debugging."
+ :version "24.4"
+ :type 'boolean)
+
+(cl-defstruct nettle-payload length data key iv input cipher cipher-mode)
+
+(defun nettle-payload-hexdump (payload)
+ (encode-hex-string (nettle-payload-data payload)))
+
+(defun nettle-payload-fulldump (payload)
+ (let ((key (funcall (nettle-payload-key payload)))
+ (iv (funcall (nettle-payload-iv payload)))
+ (input (funcall (nettle-payload-input payload))))
+ (format "%s with cipher %s, key(%d) %S, IV(%d) %S, input(%d) %S => (%d) %s"
+ (nettle-payload-cipher-mode payload)
+ (nettle-payload-cipher payload)
+ (length key) (when key (encode-hex-string key))
+ (length iv) (when iv (encode-hex-string iv))
+ (length input) (when input (encode-hex-string input))
+ (nettle-payload-length payload)
+ (nettle-payload-hexdump payload))))
+
+(defsubst nettle-make-secret (secret)
+ (if nettle-payloads-store-secrets
+ (lexical-let ((p (copy-sequence secret)))
+ (lambda () p))
+ (lambda () nil)))
+
+(defun nettle-encrypt (input key iv cipher cipher-mode)
+ (make-nettle-payload :length (length input)
+ :cipher cipher
+ :cipher-mode cipher-mode
+ :input (nettle-make-secret input)
+ :key (nettle-make-secret key)
+ :iv (nettle-make-secret iv)
+ :data (nettle-crypt t input key iv cipher cipher-mode)))
+
+(defun nettle-decrypt (payload key iv cipher cipher-mode)
+ (let ((data (nettle-crypt
+ nil
+ (nettle-payload-data payload)
+ key iv cipher cipher-mode)))
+ (substring data 0 (nettle-payload-length payload))))
+
+(ert-deftest test-nettle-001-hashes ()
+ "Test the Nettle hashing functions"
+ (progn
+ ;; we expect at least 7 hash methods
+ (should (> (length (nettle-hashes)) 7))
+ (let* ((inputs '(""
+ "some data"
+ "lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data "
+ "data and more data to go over the block limit!"
+ "data and more data to go over the block limit"))
+ (algomap '(md5 sha1 sha224 sha256 sha384 sha512))
+ ;; only test the algorithms supported by `secure-hash'
+ (hashes (delete nil (mapcar
+ (lambda (x)
+ (let ((sym (intern (car x))))
+ (car (member sym algomap))))
+ (nettle-hashes)))))
+ (dolist (hash hashes)
+ (dolist (input inputs)
+ ;; we use encode-hex-string to ensure the tests are readable
+ (should (string-equal (encode-hex-string (nettle-hash
+ input
+ (symbol-name hash)))
+ (encode-hex-string (secure-hash
+ hash
+ input
+ nil nil t)))))))))
+
+(ert-deftest test-nettle-002-ciphers ()
+ "Test the Nettle ciphers"
+ ;; we expect at least 10 ciphers
+ (should (> (length (nettle-ciphers)) 10))
+ (let ((keys '("mykey" "mykey2"))
+ (inputs '(""
+ "some data"
+ "lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data lots and lots of data "
+ "data and more data to go over the block limit!"
+ "data and more data to go over the block limit"))
+ (ivs '("" "init" "init2"))
+ ; arcfour128 generates a FPE, disabled for now
+ (ciphers (delete "arcfour128" (mapcar 'car (nettle-ciphers))))
+ (cipher-modes (nettle-cipher-modes))
+ tests test test2 result dump payload)
+
+ (dolist (mode cipher-modes)
+ (dolist (cipher ciphers)
+ (dolist (iv ivs)
+ (dolist (input inputs)
+ (dolist (key keys)
+ (setq tests (cons (list input key iv cipher mode)
+ tests)))))))
+
+ (while (setq test (pop tests))
+ ;; test2 = the original test but replacing the input with the payload
+ (setq test2 (copy-sequence test))
+ (setq payload (apply 'nettle-encrypt test))
+ (setf (nth 0 test2) payload)
+
+ (setq result (apply 'nettle-decrypt test2))
+
+ (should (string-equal (car test) result)))))
+
+;;; Testing from the command line:
+;;; echo e36a9d13c15a6df23a59a6337d6132b8f7cd5283cb4784b81141b52343a18e5f5e5ee8f5553c23167409dd222478bc30 | perl -lne 'print pack "H*", $_' | openssl enc -aes-128-ctr -d -nosalt -K 6d796b657932 -iv 696e697432 | od -x
+;;; Testing the equivalent CTR encryption:
+;;; (message "\t 111 \t %s" (nettle-payload-fulldump (nettle-encrypt "data and more data to go over the block limit" "mykey2" "init2" "aes128" "CTR")))
+;;; (message "\t 222 \t %s" (nettle-payload-fulldump (nettle-encrypt (decode-hex-string "e36a9d13c15a6df23a59a6337d6132b8f7cd5283cb4784b81141b52343a18e5f5e5ee8f5553c23167409dd222478bc30") "mykey2" "init2" "aes128" "CTR")))
+;;; (message "\t 333 \t %s" (encode-hex-string (nettle-crypt t (decode-hex-string "e36a9d13c15a6df23a59a6337d6132b8f7cd5283cb4784b81141b52343a18e5f5e5ee8f5553c23167409dd222478bc30") "mykey2" "init2" "aes128" "CTR")))
+;;; (message "\t 444 \t %s" (encode-hex-string (nettle-crypt nil (decode-hex-string "e36a9d13c15a6df23a59a6337d6132b8f7cd5283cb4784b81141b52343a18e5f5e5ee8f5553c23167409dd222478bc30") "mykey2" "init2" "aes128" "CTR")))
+
+(ert-deftest test-nettle-003-more-ciphers ()
+ "Test the Nettle ciphers from a test set"
+ (let ((tests '(
+ ("5d563f6d1cccf236051c0c5c1c58f28f" "f69f2445df4f9b17ad2b417be66c3710" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "e31a6055297d96ca3330cdf1b1860a83" "camellia256" "CBC")
+ ("e31a6055297d96ca3330cdf1b1860a83" "30c81c46a35ce411e5fbc1191a0a52ef" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "36cbeb73bd504b4070b1b7de2b21eb50" "camellia256" "CBC")
+ ("36cbeb73bd504b4070b1b7de2b21eb50" "ae2d8a571e03ac9c9eb76fac45af8e51" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "e6cfa35fc02b134a4d2c0b6737ac3eda" "camellia256" "CBC")
+ ("e6cfa35fc02b134a4d2c0b6737ac3eda" "6bc1bee22e409f96e93d7e117393172a" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "000102030405060708090a0b0c0d0e0f" "camellia256" "CBC")
+ ("01faaa930b4ab9916e9668e1428c6b08" "f69f2445df4f9b17ad2b417be66c3710" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "37d359c3349836d884e310addf68c449" "camellia192" "CBC")
+ ("37d359c3349836d884e310addf68c449" "30c81c46a35ce411e5fbc1191a0a52ef" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "5d5a869bd14ce54264f892a6dd2ec3d5" "camellia192" "CBC")
+ ("5d5a869bd14ce54264f892a6dd2ec3d5" "ae2d8a571e03ac9c9eb76fac45af8e51" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "2a4830ab5ac4a1a2405955fd2195cf93" "camellia192" "CBC")
+ ("2a4830ab5ac4a1a2405955fd2195cf93" "6bc1bee22e409f96e93d7e117393172a" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "000102030405060708090a0b0c0d0e0f" "camellia192" "CBC")
+ ("74c64268cdb8b8faf5b34e8af3732980" "f69f2445df4f9b17ad2b417be66c3710" "2b7e151628aed2a6abf7158809cf4f3c" "36a84cdafd5f9a85ada0f0a993d6d577" "camellia128" "CBC")
+ ("0f06165008cf8b8b5a63586362543e54" "30c81c46a35ce411e5fbc1191a0a52ef" "2b7e151628aed2a6abf7158809cf4f3c" "a2f2cf671629ef7840c5a5dfb5074887" "camellia128" "CBC")
+ ("a2f2cf671629ef7840c5a5dfb5074887" "ae2d8a571e03ac9c9eb76fac45af8e51" "2b7e151628aed2a6abf7158809cf4f3c" "1607cf494b36bbf00daeb0b503c831ab" "camellia128" "CBC")
+ ("1607cf494b36bbf00daeb0b503c831ab" "6bc1bee22e409f96e93d7e117393172a" "2b7e151628aed2a6abf7158809cf4f3c" "000102030405060708090a0b0c0d0e0f" "camellia128" "CBC")
+ ("7960109fb6dc42947fcfe59ea3c5eb6b" "f69f2445df4f9b17ad2b417be66c3710" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "camellia256" "ECB")
+ ("a623d711dc5f25a51bb8a80d56397d28" "30c81c46a35ce411e5fbc1191a0a52ef" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "camellia256" "ECB")
+ ("c91d3a8f1aea08a9386cf4b66c0169ea" "ae2d8a571e03ac9c9eb76fac45af8e51" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "camellia256" "ECB")
+ ("befd219b112fa00098919cd101c9ccfa" "6bc1bee22e409f96e93d7e117393172a" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "camellia256" "ECB")
+ ("909dbd95799096748cb27357e73e1d26" "f69f2445df4f9b17ad2b417be66c3710" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "camellia192" "ECB")
+ ("b40ed2b60eb54d09d030cf511feef366" "30c81c46a35ce411e5fbc1191a0a52ef" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "camellia192" "ECB")
+ ("5713c62c14b2ec0f8393b6afd6f5785a" "ae2d8a571e03ac9c9eb76fac45af8e51" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "camellia192" "ECB")
+ ("cccc6c4e138b45848514d48d0d3439d3" "6bc1bee22e409f96e93d7e117393172a" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "camellia192" "ECB")
+ ("e61925e0d5dfaa9bb29f815b3076e51a" "f69f2445df4f9b17ad2b417be66c3710" "2b7e151628aed2a6abf7158809cf4f3c" "" "camellia128" "ECB")
+ ("a0a1abcd1893ab6fe0fe5b65df5f8636" "30c81c46a35ce411e5fbc1191a0a52ef" "2b7e151628aed2a6abf7158809cf4f3c" "" "camellia128" "ECB")
+ ("0be1f14023782a22e8384c5abb7fab2b" "ae2d8a571e03ac9c9eb76fac45af8e51" "2b7e151628aed2a6abf7158809cf4f3c" "" "camellia128" "ECB")
+ ("432fc5dcd628115b7c388d770b270c96" "6bc1bee22e409f96e93d7e117393172a" "2b7e151628aed2a6abf7158809cf4f3c" "" "camellia128" "ECB")
+ ("2edf1f3418d53b88841fc8985fb1ecf2" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "" "camellia256" "ECB")
+ ("b22f3c36b72d31329eee8addc2906c68" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f1011121314151617" "" "camellia192" "ECB")
+ ("77cf412067af8270613529149919546f" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f" "" "camellia128" "ECB")
+ ("9acc237dff16d76c20ef7c919e3a7509" "0123456789abcdeffedcba9876543210" "0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff" "" "camellia256" "ECB")
+ ("b4993401b3e996f84ee5cee7d79b09b9" "0123456789abcdeffedcba9876543210" "0123456789abcdeffedcba98765432100011223344556677" "" "camellia192" "ECB")
+ ("67673138549669730857065648eabe43" "0123456789abcdeffedcba9876543210" "0123456789abcdeffedcba9876543210" "" "camellia128" "ECB")
+ ("eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223" "ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d" "001cc5b751a51d70a1c1114800000001" "aes256" "CTR")
+ ("f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884" "00faac24c1585ef15a43d87500000001" "aes256" "CTR")
+ ("145ad01dbf824ec7560863dc71e3e0c0" "53696e676c6520626c6f636b206d7367" "776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104" "00000060db5672c97aa8f0b200000001" "aes256" "CTR")
+ ("96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223" "02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe" "0007bdfd5cbd60278dcc091200000001" "aes192" "CTR")
+ ("453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a" "0096b03b020c6eadc2cb500d00000001" "aes192" "CTR")
+ ("4b55384fe259c9c84e7935a003cbe928" "53696e676c6520626c6f636b206d7367" "16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515" "0000004836733c147d6d93cb00000001" "aes192" "CTR")
+ ("c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223" "7691be035e5020a8ac6e618529f9a0dc" "00e0017b27777f3f4a1786f000000001" "aes128" "CTR")
+ ("5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "7e24067817fae0d743d6ce1f32539163" "006cb6dbc0543b59da48d90b00000001" "aes128" "CTR")
+ ("e4095d4fb7a7b3792d6175a3261311b8" "53696e676c6520626c6f636b206d7367" "ae6852f8121067cc4bf7a5765577f39e" "00000030000000000000000000000001" "aes128" "CTR")
+ ("b2eb05e2c39be9fcda6c19078c6a9d1b" "f69f2445df4f9b17ad2b417be66c3710" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "39f23369a9d9bacfa530e26304231461" "aes256" "CBC")
+ ("39f23369a9d9bacfa530e26304231461" "30c81c46a35ce411e5fbc1191a0a52ef" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "9cfc4e967edb808d679f777bc6702c7d" "aes256" "CBC")
+ ("9cfc4e967edb808d679f777bc6702c7d" "ae2d8a571e03ac9c9eb76fac45af8e51" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "f58c4c04d6e5f1ba779eabfb5f7bfbd6" "aes256" "CBC")
+ ("f58c4c04d6e5f1ba779eabfb5f7bfbd6" "6bc1bee22e409f96e93d7e117393172a" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "000102030405060708090a0b0c0d0e0f" "aes256" "CBC")
+ ("08b0e27988598881d920a9e64f5615cd" "f69f2445df4f9b17ad2b417be66c3710" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "571b242012fb7ae07fa9baac3df102e0" "aes192" "CBC")
+ ("571b242012fb7ae07fa9baac3df102e0" "30c81c46a35ce411e5fbc1191a0a52ef" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "b4d9ada9ad7dedf4e5e738763f69145a" "aes192" "CBC")
+ ("b4d9ada9ad7dedf4e5e738763f69145a" "ae2d8a571e03ac9c9eb76fac45af8e51" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "4f021db243bc633d7178183a9fa071e8" "aes192" "CBC")
+ ("4f021db243bc633d7178183a9fa071e8" "6bc1bee22e409f96e93d7e117393172a" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "000102030405060708090a0b0c0d0e0f" "aes192" "CBC")
+ ("3ff1caa1681fac09120eca307586e1a7" "f69f2445df4f9b17ad2b417be66c3710" "2b7e151628aed2a6abf7158809cf4f3c" "73bed6b8e3c1743b7116e69e22229516" "aes128" "CBC")
+ ("73bed6b8e3c1743b7116e69e22229516" "30c81c46a35ce411e5fbc1191a0a52ef" "2b7e151628aed2a6abf7158809cf4f3c" "5086cb9b507219ee95db113a917678b2" "aes128" "CBC")
+ ("5086cb9b507219ee95db113a917678b2" "ae2d8a571e03ac9c9eb76fac45af8e51" "2b7e151628aed2a6abf7158809cf4f3c" "7649abac8119b246cee98e9b12e9197d" "aes128" "CBC")
+ ("7649abac8119b246cee98e9b12e9197d" "6bc1bee22e409f96e93d7e117393172a" "2b7e151628aed2a6abf7158809cf4f3c" "000102030405060708090a0b0c0d0e0f" "aes128" "CBC")
+ ("23304b7a39f9f3ff067d8d8f9e24ecc7" "f69f2445df4f9b17ad2b417be66c3710" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "aes256" "ECB")
+ ("b6ed21b99ca6f4f9f153e7b1beafed1d" "30c81c46a35ce411e5fbc1191a0a52ef" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "aes256" "ECB")
+ ("591ccb10d410ed26dc5ba74a31362870" "ae2d8a571e03ac9c9eb76fac45af8e51" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "aes256" "ECB")
+ ("f3eed1bdb5d2a03c064b5a7e3db181f8" "6bc1bee22e409f96e93d7e117393172a" "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" "" "aes256" "ECB")
+ ("9a4b41ba738d6c72fb16691603c18e0e" "f69f2445df4f9b17ad2b417be66c3710" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "aes192" "ECB")
+ ("ef7afd2270e2e60adce0ba2face6444e" "30c81c46a35ce411e5fbc1191a0a52ef" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "aes192" "ECB")
+ ("974104846d0ad3ad7734ecb3ecee4eef" "ae2d8a571e03ac9c9eb76fac45af8e51" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "aes192" "ECB")
+ ("bd334f1d6e45f25ff712a214571fa5cc" "6bc1bee22e409f96e93d7e117393172a" "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b" "" "aes192" "ECB")
+ ("7b0c785e27e8ad3f8223207104725dd4" "f69f2445df4f9b17ad2b417be66c3710" "2b7e151628aed2a6abf7158809cf4f3c" "" "aes128" "ECB")
+ ("43b1cd7f598ece23881b00e3ed030688" "30c81c46a35ce411e5fbc1191a0a52ef" "2b7e151628aed2a6abf7158809cf4f3c" "" "aes128" "ECB")
+ ("f5d3d58503b9699de785895a96fdbaaf" "ae2d8a571e03ac9c9eb76fac45af8e51" "2b7e151628aed2a6abf7158809cf4f3c" "" "aes128" "ECB")
+ ("3ad77bb40d7a3660a89ecaf32466ef97" "6bc1bee22e409f96e93d7e117393172a" "2b7e151628aed2a6abf7158809cf4f3c" "" "aes128" "ECB")
+ ("8ea2b7ca516745bfeafc49904b496089" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" "" "aes256" "ECB")
+ ("dda97ca4864cdfe06eaf70a0ec0d7191" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f1011121314151617" "" "aes192" "ECB")
+ ("69c4e0d86a7b0430d8cdb78070b4c55a" "00112233445566778899aabbccddeeff" "000102030405060708090a0b0c0d0e0f" "" "aes128" "ECB")
+ ))
+ test expected payload result)
+ (while (setq test (pop tests))
+ ;; (message "Testing 003-ciphers %S" test)
+ (setf (nth 1 test) (decode-hex-string (nth 1 test)))
+ (setf (nth 2 test) (decode-hex-string (nth 2 test)))
+ (setf (nth 3 test) (decode-hex-string (nth 3 test)))
+ (setq expected (pop test))
+ (setq payload (apply 'nettle-encrypt test))
+ (setq result (substring (nettle-payload-data payload)
+ 0
+ (nettle-payload-length payload)))
+ (should (string-equal (encode-hex-string result)
+ expected)))))
+
+(ert-deftest test-nettle-004-more-hashes ()
+ "Test the Nettle hashes from a test set"
+ (let ((tests '(("57edf4a22be3c955ac49da2e2107b67a" "12345678901234567890123456789012345678901234567890123456789012345678901234567890" "md5")
+ ("d174ab98d277d9f5a5611c2c9f419d9f" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" "md5")
+ ("c3fcd3d76192e4007dfb496cca67e13b" "abcdefghijklmnopqrstuvwxyz" "md5")
+ ("f96b697d7cb7938d525a2f31aaf161d0" "message digest" "md5")
+ ("900150983cd24fb0d6963f7d28e17f72" "abc" "md5")
+ ("0cc175b9c0f1b6a831c399e269772661" "a" "md5")
+ ("a9993e364706816aba3e25717850c26c9cd0d89d" "abc" "sha1")))
+ test expected)
+ (while (setq test (pop tests))
+ ;; (message "Testing 004-hashes %S" test)
+ (setq expected (pop test))
+ (should (string-equal (encode-hex-string (apply 'nettle-hash test))
+ expected)))))
+
+(ert-deftest test-nettle-005-hmac-hashes ()
+ "Test the Nettle HMAC hashes from a test set"
+ (let ((tests '(("f5c5021e60d9686fef3bb0414275fe4163bece61d9a95fec7a273746a437b986" "hello\n" "test" "sha256")
+ ("46b75292b81002fd873e89c532a1b8545d6efc9822ee938feba6de2723161a67" "more and more data goes into a file to exceed the buffer size" "test" "sha256")
+ ("81568ba71fa2c5f33cc84bf362466988f98eba3735479100b4e8908acad87ac4" "more and more data goes into a file to exceed the buffer size" "very long key goes here to exceed the key size" "sha256")
+ ("4bc830005783a73b8112f4bd5f4aa5f92e05b51e9b55c0cd6f9a7bee48371def" "more and more data goes into a file to exceed the buffer size" "" "sha256")))
+ test expected)
+ (while (setq test (pop tests))
+ ;; (message "Testing 005-hmacs %S" test)
+ (setq expected (pop test))
+ (should (string-equal (encode-hex-string (apply 'nettle-hmac test))
+ expected)))))
+
+(ert-deftest test-nettle-006-pbkdf2-RFC-6070 ()
+ "Test the Nettle PBKDF2 SHA1 hashing with the RFC 6070 test set"
+ (should (string-equal (encode-hex-string (nettle-pbkdf2 "pass\000word" "sa\000lt" 4096 16 "sha1"))
+ "56fa6aa75548099dcc37d7f03425e0c3"))
+ (let ((tests '("0c60c80f961f0e71f3a9b524af6012062fe037a6:password:salt:1:x:sha1"
+ "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957:password:salt:2:x:sha1"
+ "4b007901b765489abead49d926f721d065a429c1:password:salt:4096:x:sha1"
+ ;; "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984:password:salt:16777216:x:sha1" ;; enable for a speed test :)
+ "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038:passwordPASSWORDpassword:saltSALTsaltSALTsaltSALTsaltSALTsalt:4096:x:sha1"))
+ test expected)
+ (while (and tests (setq test (split-string (pop tests) ":")))
+ (setq expected (pop test))
+ (setf (nth 2 test) (string-to-number (nth 2 test)))
+ (setf (nth 3 test) (length (decode-hex-string expected)))
+ ;; (message "Testing 006-pbkdf2-RFC-6070 %S" test)
+ (should (string-equal (encode-hex-string (apply 'nettle-pbkdf2 test))
+ expected)))))
+
+(ert-deftest test-nettle-007-rsa-verify ()
+ "Test the Nettle RSA signature verification"
+ ;; signature too short
+ (should-error (nettle-rsa-verify "Test the Nettle RSA signature"
+ ""
+ "Test the Nettle RSA signature"
+ "sha1"))
+
+ ;; key too short
+ (should-error (nettle-rsa-verify "Test the Nettle RSA signature"
+ "Test the Nettle RSA signature"
+ ""
+ "sha1"))
+
+ ;; invalid hashing method
+ (should-error (nettle-rsa-verify "Test the Nettle RSA signature"
+ "Test the Nettle RSA signature"
+ ""
+ "no such method"))
+
+ ;; key generated with:
+ ;; openssl genrsa -out privkey.pem 2048
+ ;; openssl rsa -in privkey.pem -pubout > pubkey.pem
+ (let* ((key (substring "
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreGA/Qky9W3izQV0kzba
+7wKl/wzwxkbbQxvcUqUT1krgAbO/n1tYFjXdJZoWwbMO/qv7NRoMDY4yPWGpsQfY
++PSIknAhTZVbgwXrm/wb37+hKRKax2UZ9A/Rx4vJZRYlkpvZ9LbBziseFNN7SMWW
+qkjBO/NeT8/I9mURDa+4RoYfT6ZwjTvt808PH7uIghk+MHAx9EMBAfafF1Jn9TqW
+y+Hgdqik9sZteMvCumvGK4grSwzdfPO5I05tt/0I7QVPxlXbHIk/bBsE7mpgOxur
+P0DAkFKtYDM7oZPBwB6X778ba2EEFKPpVIyzw/jlDPd9PB6gE6dixmax3Hlg69RI
+EwIDAQAB
+-----END PUBLIC KEY-----
+" 28 426))
+ ;; 24 skipped bytes are the header
+ (key-bitstring (substring (base64-decode-string key) 24)))
+ ;; invalid signature, valid key
+ (should-not (nettle-rsa-verify "Test the Nettle RSA signature"
+ "Test the Nettle RSA signature"
+ key-bitstring
+ "sha1"))
+ ;; valid signature, valid key
+ ; doesn't work; generated with "openssl rsautl -sign -in /tmp/test -inkey /tmp/privkey.pem" but contains other baggage
+ (should (nettle-rsa-verify "Test the Nettle RSA signature"
+ (decode-hex-string "abf710d920de0a210167e62995d5cb06fb0ff6a3f81e2f1965dd3f4716883ab61b7dec40d1ebde89b0657473a434d0333177f183f71a9f4b84a49781b1e4bc440e042f2eb4441000ba07168cdb190c5aebba8c433420f6fc28b6997cbfee061170210bfa65294199e6d6c8c5e1a16421942371f6115d77263b859a75645b6b70d56f14ad378c8499318ff05eda9d24a61d854a3d7f6b67b037abb8d25e4b11ca3e42bdb823cfac34c70057ecd55cbb8449346c0824b46f6c668d14f1744bad7d05470953981df32fde24d2a1f27e58bf9e7d99b20b39b25844c53945dcbbd8b406e78bc0b8aee48c0ec8a26e70301eeeb12ba733e0baf7b82c8e25ac3ee89291")
+ key-bitstring
+ "sha1"))
+))
+
+;; (message (encode-hex-string (nettle-pbkdf2 "password" "salt" 1 20 "sha1")))
+
+(provide 'nettle)
+;;; nettle.el ends here
=== modified file 'src/Makefile.in'
--- src/Makefile.in 2013-09-15 17:58:46 +0000
+++ src/Makefile.in 2013-10-06 08:57:33 +0000
@@ -307,6 +307,9 @@
LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBNETTLE_LIBS = @LIBNETTLE_LIBS@
+LIBNETTLE_CFLAGS = @LIBNETTLE_CFLAGS@
+
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
INTERVALS_H = dispextern.h intervals.h composite.h
@@ -349,7 +352,7 @@
$(LIBXML2_CFLAGS) $(DBUS_CFLAGS) $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) \
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
- $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \
+ $(LIBGNUTLS_CFLAGS) $(LIBNETTLE_CFLAGS) $(GFILENOTIFY_CFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
@@ -373,7 +376,7 @@
alloc.o data.o doc.o editfns.o callint.o \
eval.o floatfns.o fns.o font.o print.o lread.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
- process.o gnutls.o callproc.o \
+ process.o gnutls.o nettle.o callproc.o \
region-cache.o sound.o atimer.o \
doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
profiler.o decompress.o \
@@ -430,7 +433,7 @@
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
- $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
+ $(LIBGNUTLS_LIBS) $(LIBNETTLE_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
$(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ)
all: emacs$(EXEEXT) $(OTHER_FILES)
=== modified file 'src/emacs.c'
--- src/emacs.c 2013-09-20 15:34:36 +0000
+++ src/emacs.c 2013-10-06 08:57:33 +0000
@@ -84,6 +84,10 @@
#include "gnutls.h"
#endif
+#ifdef HAVE_NETTLE
+#include "nettle.h"
+#endif
+
#if (defined PROFILING \
&& (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__))
# include <sys/gmon.h>
@@ -1450,6 +1454,10 @@
syms_of_gnutls ();
#endif
+#ifdef HAVE_NETTLE
+ syms_of_nettle ();
+#endif
+
#ifdef HAVE_GFILENOTIFY
syms_of_gfilenotify ();
#endif /* HAVE_GFILENOTIFY */
=== added file 'src/nettle.c'
--- src/nettle.c 1970-01-01 00:00:00 +0000
+++ src/nettle.c 2013-10-06 08:57:33 +0000
@@ -0,0 +1,505 @@
+/* libnettle+libhogweed glue for GNU Emacs.
+ Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <errno.h>
+
+#include "lisp.h"
+
+#ifdef HAVE_NETTLE
+
+#include "nettle.h"
+
+DEFUN ("nettle-available-p", Fnettle_available_p, Snettle_available_p, 0, 0, 0,
+ doc: /* Return t if libnettle+libhogweed are available in this instance of Emacs. */)
+ (void)
+{
+ return Qt;
+}
+
+DEFUN ("nettle-hash", Fnettle_hash, Snettle_hash, 2, 2, 0,
+ doc: /* Hash INPUT string with HASH-METHOD into a unibyte string.
+
+The list of hash-methods can be obtained with `nettle-hashes`.
+The `sha256' hashing method is recommended by the libnettle documentation. */)
+ (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 (0 == strcmp (SDATA (hash_method), nettle_hashes[i]->name))
+ {
+ 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 (digest, length);
+
+ free (digest);
+ free (ctx);
+ }
+ }
+
+ if (NILP (ret))
+ {
+ error ("Nettle hash-method %s was not found", SDATA (hash_method));
+ }
+
+ return ret;
+}
+
+DEFUN ("nettle-hmac", Fnettle_hmac, Snettle_hmac, 3, 3, 0,
+ doc: /* Hash INPUT string with HASH-METHOD and KEY into a unibyte string according to HMAC (RFC 2104).
+
+The list of hash-methods can be obtained with `nettle-hashes`.
+The `sha256' hashing method is recommended by the libnettle documentation. */)
+ (Lisp_Object input, Lisp_Object key, Lisp_Object hash_method)
+{
+ Lisp_Object ret = Qnil;
+
+ CHECK_STRING (input);
+ CHECK_STRING (hash_method);
+ CHECK_STRING (key);
+
+ for (int i = 0; NULL != nettle_hashes[i]; i++)
+ {
+ if (0 == strcmp (SDATA (hash_method), nettle_hashes[i]->name))
+ {
+ const struct nettle_hash *alg = nettle_hashes[i];
+ unsigned int length = alg->digest_size;
+ void *inner_ctx = xzalloc (alg->context_size);
+ void *outer_ctx = xzalloc (alg->context_size);
+ void *state_ctx = xzalloc (alg->context_size);
+ uint8_t *digest;
+
+ hmac_set_key (outer_ctx, inner_ctx, state_ctx, alg, SCHARS (key), SDATA (key));
+ hmac_update (state_ctx, alg, SCHARS (input), SDATA (input));
+ digest = xzalloc (length);
+ hmac_digest (outer_ctx, inner_ctx, state_ctx, alg, length, digest);
+
+ ret = make_unibyte_string (digest, length);
+
+ free (digest);
+ free (state_ctx);
+ free (outer_ctx);
+ free (inner_ctx);
+ }
+ }
+
+ if (NILP (ret))
+ {
+ error ("Nettle hash-method %s was not found", SDATA (hash_method));
+ }
+
+ return ret;
+}
+
+DEFUN ("nettle-pbkdf2", Fnettle_pbkdf2, Snettle_pbkdf2, 5, 5, 0,
+ doc: /* Derive PBKDF2 of length HASH-LENGTH from KEY string with HASH-METHOD using ITERATIONS and SALT into 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. */)
+ (Lisp_Object key, Lisp_Object salt, Lisp_Object iterations, Lisp_Object hash_length, Lisp_Object hash_method)
+{
+ Lisp_Object ret = Qnil;
+ bool sha1_mode = false;
+ bool sha256_mode = false;
+ int outlength = 0;
+
+ CHECK_STRING (salt);
+ CHECK_STRING (hash_method);
+ CHECK_STRING (key);
+ CHECK_NUMBER (iterations);
+ CHECK_NUMBER (hash_length);
+
+ outlength = XINT (hash_length);
+
+ sha1_mode = 0 == strcmp (SDATA (hash_method), "sha1");
+ sha256_mode = 0 == strcmp (SDATA (hash_method), "sha256");
+
+ if (sha1_mode)
+ {
+ uint8_t *digest = xzalloc (outlength);
+ pbkdf2_hmac_sha1 (SCHARS (key), SDATA (key), XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
+ ret = make_unibyte_string (digest, outlength);
+ free (digest);
+ }
+ else if (sha256_mode)
+ {
+ uint8_t *digest = xzalloc (outlength);
+ pbkdf2_hmac_sha256 (SCHARS (key), SDATA (key), XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
+ ret = make_unibyte_string (digest, outlength);
+ free (digest);
+ }
+ else
+ {
+ error ("Nettle hash-method %s is not supported yet, sorry", SDATA (hash_method));
+ }
+
+ /* TODO: figure out why this doesn't work correctly. For now only sha1 and sha256 are supported.
+ for (int i = 0; NULL != nettle_hashes[i]; i++)
+ {
+ if (0 == strcmp (SDATA (hash_method), nettle_hashes[i]->name))
+ {
+ const struct nettle_hash *alg = nettle_hashes[i];
+ unsigned int length = alg->digest_size;
+ void *ctx = NULL;
+ uint8_t *digest = xzalloc (outlength);
+ int csize = alg->context_size;
+
+ message("Generating PBKDF2 with cipher %s, key(%d) '%s', salt(%d) '%s', iterations %d", alg->name, SCHARS (key), SDATA (key), SCHARS (salt), SDATA (salt), XINT (iterations));
+ ctx = xzalloc (3*csize);
+
+ // HMAC_SET_KEY(ctx, alg, SCHARS (key), SDATA (key));
+ // PBKDF2 (ctx, alg->update, alg->digest, length, XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
+ message("first 4 bytes generated => %x %x %x %x", digest[0], digest[1], digest[2], digest[3] );
+
+ ret = make_unibyte_string (digest, outlength);
+
+ free (digest);
+ free (ctx);
+ }
+ }
+ */
+
+ if (NILP (ret))
+ {
+ error ("Nettle hash-method %s was not found", SDATA (hash_method));
+ }
+
+ return ret;
+}
+
+DEFUN ("nettle-rsa-verify", Fnettle_rsa_verify, Snettle_rsa_verify, 4, 4, 0,
+ doc: /* Verify that the RSA SIGNATURE of DATA was created with PUBLIC-KEY according to HASH-METHOD.
+
+The list of hash-methods can be obtained with `nettle-hashes`.
+Only the `md5', `sha1', `sha256', and `sha512' hashing methods are supported. */)
+ (Lisp_Object data, Lisp_Object signature, Lisp_Object public_key, Lisp_Object hash_method)
+{
+ Lisp_Object ret = Qnil;
+ bool md5_mode = false;
+ bool sha1_mode = false;
+ bool sha256_mode = false;
+ bool sha512_mode = false;
+ struct rsa_public_key key;
+ mpz_t s;
+
+ CHECK_STRING (data);
+ CHECK_STRING (signature);
+ CHECK_STRING (public_key);
+ CHECK_STRING (hash_method);
+
+ if (SCHARS (signature) < 16)
+ {
+ error ("RSA signature must be at least 16 bytes long");
+ }
+
+ mpz_init(s);
+ if (!mpz_set_str(s, SDATA (signature), 16))
+ {
+ error ("RSA signature could not be loaded");
+ }
+
+ rsa_public_key_init(&key);
+
+ if (!rsa_keypair_from_der (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)) &&
+ !rsa_keypair_from_sexp (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)))
+ {
+ char* p = SDATA (public_key);
+ if (SCHARS (public_key) > 3)
+ {
+ // message("first 4 bytes of bad public key => %x %x %x %x", p[0], p[1], p[2], p[3] );
+ }
+ error ("RSA public key could not be loaded in binary or DER formats");
+ }
+
+ md5_mode = 0 == strcmp (SDATA (hash_method), "md5");
+ sha1_mode = 0 == strcmp (SDATA (hash_method), "sha1");
+ sha256_mode = 0 == strcmp (SDATA (hash_method), "sha256");
+ sha512_mode = 0 == strcmp (SDATA (hash_method), "sha512");
+
+ if (sha1_mode)
+ {
+ struct sha1_ctx hash;
+
+ sha1_init(&hash);
+ sha1_update(&hash, SCHARS (data), SDATA (data));
+
+ if (rsa_sha1_verify(&key, &hash, s))
+ {
+ ret = Qt;
+ }
+ }
+ else
+ {
+ error ("Nettle hash-method %s is not supported yet, sorry", SDATA (hash_method));
+ }
+
+ mpz_clear(s);
+ rsa_public_key_clear(&key);
+
+ return ret;
+}
+
+DEFUN ("nettle-hashes", Fnettle_hashes, Snettle_hashes, 0, 1, 0,
+ doc: /* Return alist of Nettle hash names and their digest and block sizes.
+With the optional NAME, returns just one hash's info (NAME DIGESTSIZE BLOCKSIZE). */)
+ (Lisp_Object name)
+{
+ Lisp_Object hashes = Qnil;
+
+ if (! NILP (name))
+ {
+ CHECK_STRING (name);
+ }
+
+ for (int i = 0; nettle_hashes[i] != NULL; i++)
+ {
+ Lisp_Object hash = Fcons (build_string (nettle_hashes[i]->name),
+ list2i (nettle_hashes[i]->digest_size,
+ nettle_hashes[i]->block_size));
+
+ if (! NILP (name) && 0 == strcmp (SDATA (name), nettle_hashes[i]->name))
+ {
+ return hash;
+ }
+
+ hashes = Fcons (hash, hashes);
+ }
+
+ if (NILP (name))
+ {
+ return hashes;
+ }
+
+ return Qnil;
+}
+
+DEFUN ("nettle-crypt", Fnettle_crypt, Snettle_crypt, 6, 6, 0,
+ doc: /* Encrypt or decrypt based on CRYPT-MODE INPUT string with unibyte KEY and CIPHER and CIPHER-MODE, seeding with IV, into a unibyte string.
+
+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. */)
+ (Lisp_Object crypt_mode, Lisp_Object input, Lisp_Object key, Lisp_Object iv, Lisp_Object cipher, Lisp_Object cipher_mode)
+{
+ Lisp_Object ret = Qnil;
+ Lisp_Object mode = Qnil;
+ bool decrypt = NILP(crypt_mode);
+ bool ctr_mode = false;
+
+ CHECK_STRING (input);
+ CHECK_SYMBOL (crypt_mode);
+ CHECK_STRING (key);
+ CHECK_STRING (iv);
+ CHECK_STRING (cipher);
+ CHECK_STRING (cipher_mode);
+
+ mode = CAR_SAFE (Fmember (cipher_mode, Fnettle_cipher_modes ()));
+
+ ctr_mode = 0 == strcmp (SDATA (mode), "CTR");
+
+ if (NILP (mode))
+ {
+ error ("Nettle cipher mode %s was not found", SDATA (cipher_mode));
+ }
+
+ for (int i = 0; NULL != nettle_ciphers[i]; i++)
+ {
+ if (0 == strcmp (SDATA (cipher), nettle_ciphers[i]->name))
+ {
+ const struct nettle_cipher *alg = nettle_ciphers[i];
+ unsigned int input_length = SCHARS (input);
+ void *ctx = xzalloc (alg->context_size);
+ void *dest = NULL;
+ char *key_hold = NULL;
+ char *iv_hold = NULL;
+
+ /* Increment input_length to the next multiple of block_size. */
+ if (0 != alg->block_size)
+ {
+ while (0 != (input_length % alg->block_size))
+ {
+ input_length++;
+ }
+ }
+
+ // message("Input length is %d and the block size is %d", input_length, alg->block_size);
+
+ dest = xzalloc (input_length);
+ memcpy (dest, SDATA (input), SCHARS (input));
+ // message("Dest buffer: '%s' and size is %d", dest, input_length);
+
+ key_hold = xzalloc (alg->key_size);
+ memcpy (key_hold, SDATA (key), min (alg->key_size, SCHARS (key)));
+
+ iv_hold = xzalloc (alg->block_size);
+ memcpy (iv_hold, SDATA (iv), SCHARS (iv));
+
+ // message("Key buffer: '%s' and key size %d", key_hold, alg->key_size);
+
+ // in CTR mode we use set_encrypt_key regardless
+ if (decrypt && !ctr_mode)
+ {
+ alg->set_decrypt_key (ctx, alg->key_size, key_hold);
+ }
+ else
+ {
+ alg->set_encrypt_key (ctx, alg->key_size, key_hold);
+ }
+
+ // message("%s %s with cipher %s, key(%d) '%s', IV(%d) '%s', input(%d) '%s'", SDATA (mode), decrypt ? "decrypting" : "encrypting", alg->name, SCHARS (key), SDATA (key), SCHARS (iv), SDATA (iv), SCHARS (input), SDATA (input));
+ if (0 == strcmp (SDATA (mode), "ECB"))
+ {
+ if (decrypt)
+ {
+ alg->decrypt (ctx, input_length, dest, dest);
+ }
+ else
+ {
+ alg->encrypt (ctx, input_length, dest, dest);
+ }
+ }
+ else if (0 == strcmp (SDATA (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 (dest, input_length);
+
+ free (iv_hold);
+ free (key_hold);
+ free (dest);
+ free (ctx);
+ }
+ }
+
+ if (NILP (ret))
+ {
+ error ("Nettle cipher %s was not found", SDATA (cipher));
+ }
+
+ return ret;
+}
+
+DEFUN ("nettle-ciphers", Fnettle_ciphers, Snettle_ciphers, 0, 1, 0,
+ doc: /* Return alist of Nettle cipher names and their key and block sizes.
+With the optional NAME, returns just one cipher's info (NAME KEYSIZE BLOCKSIZE). */)
+ (Lisp_Object name)
+{
+ Lisp_Object ciphers = Qnil;
+
+ if (! NILP (name))
+ {
+ CHECK_STRING (name);
+ }
+
+ for (int i = 0; nettle_ciphers[i] != NULL; i++)
+ {
+ Lisp_Object cipher = Fcons (build_string (nettle_ciphers[i]->name),
+ list2i (nettle_ciphers[i]->key_size,
+ nettle_ciphers[i]->block_size));
+
+ if (! NILP (name) && 0 == strcmp (SDATA (name), nettle_ciphers[i]->name))
+ {
+ return cipher;
+ }
+
+ ciphers = Fcons (cipher, ciphers);
+ }
+
+ if (NILP (name))
+ {
+ return ciphers;
+ }
+
+ return Qnil;
+}
+
+DEFUN ("nettle-cipher-modes", Fnettle_cipher_modes, Snettle_cipher_modes, 0, 0, 0,
+ doc: /* Return the list of Nettle cipher modes as strings. */)
+ (void)
+{
+ Lisp_Object modes = Qnil;
+ modes = Fcons (build_string ("ECB"), modes);
+ modes = Fcons (build_string ("CBC"), modes);
+ modes = Fcons (build_string ("CTR"), modes);
+ /* GCM is unsupported for now
+ modes = Fcons (build_string ("GCM"), modes);
+ */
+ return modes;
+}
+
+void
+syms_of_nettle (void)
+{
+ defsubr (&Snettle_available_p);
+ defsubr (&Snettle_hash);
+ defsubr (&Snettle_hashes);
+ defsubr (&Snettle_crypt);
+ defsubr (&Snettle_ciphers);
+ defsubr (&Snettle_cipher_modes);
+ defsubr (&Snettle_rsa_verify);
+ // defsubr (&Snettle_dsa);
+ // defsubr (&Snettle_ecc);
+ defsubr (&Snettle_hmac);
+ defsubr (&Snettle_pbkdf2);
+ /* Not implemented yet. defsubr (&Snettle_umac); */
+}
+
+#endif /* HAVE_NETTLE */
=== added file 'src/nettle.h'
--- src/nettle.h 1970-01-01 00:00:00 +0000
+++ src/nettle.h 2013-10-06 08:57:33 +0000
@@ -0,0 +1,57 @@
+/* libnettle+libhogweed glue for GNU Emacs.
+ Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef EMACS_NETTLE_DEFINED
+#define EMACS_NETTLE_DEFINED
+
+#ifdef HAVE_NETTLE
+
+/* PGP protocol helpers. */
+#include <nettle/pgp.h>
+
+/* Public-key crypto. */
+#include <nettle/rsa.h>
+#include <nettle/dsa.h>
+#include <nettle/ecc.h>
+#include <nettle/pkcs1.h>
+
+#include <nettle/nettle-meta.h>
+
+/* Cipher modes. */
+
+#include <nettle/cbc.h>
+#include <nettle/ctr.h>
+#include <nettle/gcm.h>
+
+/* Keyed hash functions. */
+#include <nettle/hmac.h>
+#include <nettle/umac.h>
+
+/* Key derivation functions. */
+
+#include <nettle/pbkdf2.h>
+
+/* Randomness functions. */
+
+#include <nettle/yarrow.h>
+
+#endif
+
+extern void syms_of_nettle (void);
+
+#endif
# Begin bundle
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
^ permalink raw reply [flat|nested] 37+ messages in thread
* bignum support in Emacs with libgmp (was: GNU Emacs-libnettle-libhogweed integration patch v1)
2013-10-06 9:15 GNU Emacs-libnettle-libhogweed integration patch v1 Ted Zlatanov
@ 2013-10-06 9:58 ` Ted Zlatanov
2013-10-06 16:09 ` GNU Emacs-libnettle-libhogweed integration patch v1 Eli Zaretskii
2013-10-06 16:51 ` Stefan Monnier
2 siblings, 0 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-06 9:58 UTC (permalink / raw)
To: emacs-devel
I remember we discussed a while ago that Emacs has bignum support in the
`calc' package and that native Emacs integers were not adequate
sometimes for large arithmetic.
I wanted to propose that we consider exposing the libgmp
(http://gmplib.org/ http://gmplib.org/manual/) functions to the Emacs
core for managing bignums; specifically the mpz, mpq, and mpf functions.
That would give Emacs powerful bignum arithmetic at (I hope) better
speeds than a native ELisp implementation. libgmp is quite mature.
The existing bignum support can remain as a fallback with refactoring or
just remain as is. The new functionality would probably have to
introduce new Lisp types.
I don't plan to do the work myself currently but it would make a nice
project if anyone is interested in picking it up.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 9:15 GNU Emacs-libnettle-libhogweed integration patch v1 Ted Zlatanov
2013-10-06 9:58 ` bignum support in Emacs with libgmp (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
@ 2013-10-06 16:09 ` Eli Zaretskii
2013-10-06 21:07 ` Ted Zlatanov
2013-10-06 16:51 ` Stefan Monnier
2 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2013-10-06 16:09 UTC (permalink / raw)
To: emacs-devel
> From: Ted Zlatanov <tzz@lifelogs.com>
> Date: Sun, 06 Oct 2013 05:15:09 -0400
> Cc: nettle-bugs@lists.lysator.liu.se
>
> This is the first cut of the Nettle integration for your review.
Thanks.
> +DEFUN ("nettle-available-p", Fnettle_available_p, Snettle_available_p, 0, 0, 0,
> + doc: /* Return t if libnettle+libhogweed are available in this instance of Emacs. */)
> + (void)
> +{
> + return Qt;
> +}
For the record: this will have to be changed for MS-Windows, to
support dynamic loading, like we do, e.g., in decompress.c.
> +DEFUN ("nettle-hmac", Fnettle_hmac, Snettle_hmac, 3, 3, 0,
> + doc: /* Hash INPUT string with HASH-METHOD and KEY into a unibyte string according to HMAC (RFC 2104).
The first line of the doc string is too long. (There are others with
similar problems.)
> + digest = xzalloc (length);
> + hmac_digest (outer_ctx, inner_ctx, state_ctx, alg, length, digest);
> +
> + ret = make_unibyte_string (digest, length);
Instead of xzalloc, then make_unibyte_string, I think you should be
able to allocate a string first, and then work on its SDATA. This
will save you from at least one allocation.
> + free (digest);
> + free (state_ctx);
> + free (outer_ctx);
> + free (inner_ctx);
We tend to use xfree, not free.
> + sha1_mode = 0 == strcmp (SDATA (hash_method), "sha1");
> + sha256_mode = 0 == strcmp (SDATA (hash_method), "sha256");
Perhaps using Fstring_equal is better here, not sure.
> + uint8_t *digest = xzalloc (outlength);
^^^^^^^
Why not 'unsigned char'?
> + if (!rsa_keypair_from_der (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)) &&
> + !rsa_keypair_from_sexp (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)))
The && should be at the beginning of a line, not at the end.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 9:15 GNU Emacs-libnettle-libhogweed integration patch v1 Ted Zlatanov
2013-10-06 9:58 ` bignum support in Emacs with libgmp (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
2013-10-06 16:09 ` GNU Emacs-libnettle-libhogweed integration patch v1 Eli Zaretskii
@ 2013-10-06 16:51 ` Stefan Monnier
2013-10-06 16:58 ` Eli Zaretskii
2013-10-06 21:19 ` Ted Zlatanov
2 siblings, 2 replies; 37+ messages in thread
From: Stefan Monnier @ 2013-10-06 16:51 UTC (permalink / raw)
To: emacs-devel
> This is the first cut of the Nettle integration for your review.
I generally dislike adding library dependencies to Emacs, even for
libraries on which we already depend transitively. So, there has to be
a very good use case for it.
Currently, I don't see such a use case, so I'm not interested.
Implementing an FFI would of course make it unnecessary for you (or
anyone else) to convince me first, so I encourage you to work on the FFI
as a first step.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 16:51 ` Stefan Monnier
@ 2013-10-06 16:58 ` Eli Zaretskii
2013-10-06 21:19 ` Ted Zlatanov
1 sibling, 0 replies; 37+ messages in thread
From: Eli Zaretskii @ 2013-10-06 16:58 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sun, 06 Oct 2013 12:51:39 -0400
>
> Implementing an FFI would of course make it unnecessary for you (or
> anyone else) to convince me first, so I encourage you to work on the FFI
> as a first step.
It might be educational and useful for the FFI discussion to describe
the steps needed to integrate libhogweed with Emacs using libffi. We
will then be able to compare that with the patch proposed by Ted, and
see which of the steps are one-time effort, required for providing FFI
infrastructure, and which are to be repeated for every foreign
library. Otherwise, I fear that the discussion about FFI is not
really based on good understanding of what is involved.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 16:09 ` GNU Emacs-libnettle-libhogweed integration patch v1 Eli Zaretskii
@ 2013-10-06 21:07 ` Ted Zlatanov
0 siblings, 0 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-06 21:07 UTC (permalink / raw)
To: emacs-devel
On Sun, 06 Oct 2013 19:09:41 +0300 Eli Zaretskii <eliz@gnu.org> wrote:
EZ> For the record: this will have to be changed for MS-Windows, to
EZ> support dynamic loading, like we do, e.g., in decompress.c.
Yup, I figured it would, but I don't know that part of the code well.
>> +DEFUN ("nettle-hmac", Fnettle_hmac, Snettle_hmac, 3, 3, 0,
>> + doc: /* Hash INPUT string with HASH-METHOD and KEY into a unibyte string according to HMAC (RFC 2104).
EZ> The first line of the doc string is too long. (There are others with
EZ> similar problems.)
OK, redone. One just can't be shortened easily:
Make PBKDF2 of HASH-LENGTH from KEY with HASH-METHOD using ITERATIONS and SALT.
EZ> Instead of xzalloc, then make_unibyte_string, I think you should be
EZ> able to allocate a string first, and then work on its SDATA. This
EZ> will save you from at least one allocation.
Hmm, I thought about that, but typically Nettle wants to work on pure C
strings and it's nice to avoid corrupting Lisp strings. Other than
saving the allocation, are there other benefits?
EZ> We tend to use xfree, not free.
OK; fixed.
>> + sha1_mode = 0 == strcmp (SDATA (hash_method), "sha1");
>> + sha256_mode = 0 == strcmp (SDATA (hash_method), "sha256");
EZ> Perhaps using Fstring_equal is better here, not sure.
OK with me either way. I didn't want to use symbols because Nettle uses
strings... but maybe symbols are the right approach anyhow.
>> + uint8_t *digest = xzalloc (outlength);
EZ> ^^^^^^^
EZ> Why not 'unsigned char'?
Nettle uses those.
>> + if (!rsa_keypair_from_der (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)) &&
>> + !rsa_keypair_from_sexp (&key, NULL, 0, SCHARS (public_key), SDATA (public_key)))
EZ> The && should be at the beginning of a line, not at the end.
Oh, I always forget that. Fixed.
I won't post the revised patch, it's too trivial :) But I could publish
the branch in the Emacs repo if it's OK with you and/or Stefan?
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 16:51 ` Stefan Monnier
2013-10-06 16:58 ` Eli Zaretskii
@ 2013-10-06 21:19 ` Ted Zlatanov
2013-10-07 4:02 ` Stefan Monnier
1 sibling, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-06 21:19 UTC (permalink / raw)
To: emacs-devel
On Sun, 06 Oct 2013 12:51:39 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> This is the first cut of the Nettle integration for your review.
SM> I generally dislike adding library dependencies to Emacs, even for
SM> libraries on which we already depend transitively. So, there has to be
SM> a very good use case for it.
SM> Currently, I don't see such a use case, so I'm not interested.
I certainly hope others see the utility of the work, especially so I can
implement OpenPGP support and avoid depending on the external GnuPG
binary for verifying package signatures. It would also let me implement
binary signatures of Emacs data (to make sure it's not corrupted) and
true secrets (Lisp data strings that can't be decoded without the right
key). But I've stated all this already, so it's unfortunate that I have
to restate and defend it.
Meanwhile I will try to finish the patch, but it's discouraging to have
to argue for basic security in Emacs for years and to spend significant
time writing code that will hang in limbo and may need to be
significantly rebased by the time it's accepted (if ever).
SM> Implementing an FFI would of course make it unnecessary for you (or
SM> anyone else) to convince me first, so I encourage you to work on the FFI
SM> as a first step.
Well, sure, I'd love to, if I knew anything about the topic. I can help
document and test things, and maybe review some of the code. My primary
concern is that I have to redo a significant amount of work by the time
the Nettle patch is accepted, so it would have been nice to state your
opposal earlier. I certainly stated my intentions clearly.
Thanks
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-06 21:19 ` Ted Zlatanov
@ 2013-10-07 4:02 ` Stefan Monnier
2013-10-07 11:41 ` Ted Zlatanov
0 siblings, 1 reply; 37+ messages in thread
From: Stefan Monnier @ 2013-10-07 4:02 UTC (permalink / raw)
To: emacs-devel
> I certainly hope others see the utility of the work, especially so I can
> implement OpenPGP support and avoid depending on the external GnuPG
> binary for verifying package signatures.
Yes, we've been through this in the past, and my position is still the
same: I don't want to have to maintain an OpenPGP implementation in
Emacs when we can outsource this maintenance to the GPG guys. We have
enough trouble with code we can't outsource. Especially for code that
touches security and cryptography where it's all too easy to make very
subtle mistakes.
IOW I wouldn't oppose bindings to a libgpg on the same grounds (tho
such bindings probably wouldn't be very useful if all they do is
replace a dependency on "external gpg executable" with a dependency on
libgpg, where libgpg is not more likely to be installed than gpg).
> It would also let me implement binary signatures of Emacs data (to
> make sure it's not corrupted)
I don't know what that is.
> and true secrets (Lisp data strings that can't be decoded without the
> right key).
We try our best to make sure Emacs doesn't crash on the user.
That's a very far cry from making Emacs code sufficiently secure that
the data we keep in Emacs heap can be considered secret.
And even besides latent security holes, I don't even know how you
intend to make such a "secret" work (who'd be prevented from
seeing/using it?).
IOW it's much too hypothetical to justify accepting such bindings.
> the Nettle patch is accepted, so it would have been nice to state your
> opposal earlier. I certainly stated my intentions clearly.
I stated it many times already in earlier discussions.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-07 4:02 ` Stefan Monnier
@ 2013-10-07 11:41 ` Ted Zlatanov
2013-10-07 22:03 ` Ted Zlatanov
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-07 11:41 UTC (permalink / raw)
To: emacs-devel
On Mon, 07 Oct 2013 00:02:37 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> the Nettle patch is accepted, so it would have been nice to state your
>> opposal earlier. I certainly stated my intentions clearly.
SM> I stated it many times already in earlier discussions.
I didn't realize you would actually reject a working, optionally enabled
piece of functionality. Sorry for misunderstanding today's Emacs
development model, and I hope you change your mind at some point.
Consider my patch withdrawn.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-07 11:41 ` Ted Zlatanov
@ 2013-10-07 22:03 ` Ted Zlatanov
2013-10-07 22:58 ` Stefan Monnier
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-07 22:03 UTC (permalink / raw)
To: emacs-devel
On Mon, 07 Oct 2013 07:41:39 -0400 Ted Zlatanov <tzz@lifelogs.com> wrote:
TZ> On Mon, 07 Oct 2013 00:02:37 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>>> the Nettle patch is accepted, so it would have been nice to state your
>>> opposal earlier. I certainly stated my intentions clearly.
SM> I stated it many times already in earlier discussions.
TZ> I didn't realize you would actually reject a working, optionally enabled
TZ> piece of functionality. Sorry for misunderstanding today's Emacs
TZ> development model, and I hope you change your mind at some point.
TZ> Consider my patch withdrawn.
Huh. So I was looking at updating GnuTLS to version 3.x for a
completely unrelated reason (updating Emacs support for it) and found
that it exposes most of the Nettle functions in a convenient form:
basically a thin layer on top with different function names. This is
new in 3.x and had slipped my notice:
http://gnutls.org/manual/html_node/Cryptographic-API.html#Cryptographic-API
If I changed my proposal to use the GnuTLS interface functions, so no
new library dependencies are added, would it be acceptable?
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: GNU Emacs-libnettle-libhogweed integration patch v1
2013-10-07 22:03 ` Ted Zlatanov
@ 2013-10-07 22:58 ` Stefan Monnier
2013-10-07 23:43 ` Emacs crypto use cases (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
0 siblings, 1 reply; 37+ messages in thread
From: Stefan Monnier @ 2013-10-07 22:58 UTC (permalink / raw)
To: emacs-devel
> If I changed my proposal to use the GnuTLS interface functions, so no
> new library dependencies are added, would it be acceptable?
It'd be a bit less bad, but basically the main problems remain:
- no clear and concrete use-case.
- I want these things to go through an FFI.
- I don't want to have an OpenPGP implementation to maintain.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Emacs crypto use cases (was: GNU Emacs-libnettle-libhogweed integration patch v1)
2013-10-07 22:58 ` Stefan Monnier
@ 2013-10-07 23:43 ` Ted Zlatanov
2013-10-08 3:02 ` Emacs crypto use cases Stefan Monnier
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-07 23:43 UTC (permalink / raw)
To: emacs-devel
On Mon, 07 Oct 2013 18:58:00 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> If I changed my proposal to use the GnuTLS interface functions, so no
>> new library dependencies are added, would it be acceptable?
SM> It'd be a bit less bad, but basically the main problems remain:
SM> - no clear and concrete use-case.
SM> - I want these things to go through an FFI.
SM> - I don't want to have an OpenPGP implementation to maintain.
I can't help the FFI problem, but you already depend on libgnutls so I
don't see what difference it makes here.
I don't have to put the OpenPGP implementation in the Emacs core, if it
can be put in a package. Actually GnuTLS has some work in that
direction (as of 3.1) so it may turn out to be fairly trivial on our
side, but then without FFI it would have to be supported in the core. I
don't really care that much about the delivery method as long as it
works.
Regarding the use cases, you could look at the algorithms in
http://gnutls.org/manual/html_node/Using-GnuTLS-as-a-cryptographic-library.html#Using-GnuTLS-as-a-cryptographic-library
and see for yourself that they form a general toolbox that will serve
the Emacs core well. I will make an effort here to list some use cases,
but I am positive there will be more as time goes on. I would
appreciate it if anyone else interested in this work added their use
cases or vote of support.
- symmetric encryption without the burden or risk of shelling out
(http://gnutls.org/manual/html_node/Encryption-algorithms-used-in-the-record-layer.html#tab_003aciphers).
I would love to use this instead of the painfully heavy GnuPG
integration for the symmetric case.
- HMAC keyed hashing (http://www.ietf.org/rfc/rfc2104.txt) allowing
message authentication with a shared key. For instance, that would
allow the Emacs client and server to authenticate the data they share
without a full PPK infrastructure, or check that some shared memory
hasn't been corrupted... it's a general authentication mechanism for
content.
- asymmetric (public-private key) operations: encrypt and verify data.
This is obiously the foundation of package signing in an OpenPGP
implementation, but is useful on its own. My use case is storing
secret data in Emacs in an encrypted format, so it can't be decoded
trivially. The private key can be protected from a memory dump in
many ways depending on the platform (e.g. the Secrets API). A full
OpenPGP protocol for this would be overkill.
- OpenPGP support: allow package.el signing verification without GnuPG
on the platform and much more.
I hope this is helpful.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Emacs crypto use cases
2013-10-07 23:43 ` Emacs crypto use cases (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
@ 2013-10-08 3:02 ` Stefan Monnier
2013-10-08 10:33 ` Ted Zlatanov
0 siblings, 1 reply; 37+ messages in thread
From: Stefan Monnier @ 2013-10-08 3:02 UTC (permalink / raw)
To: emacs-devel
> I can't help the FFI problem,
Can't see why not. On the contrary, you have a perfect use case for the
FFI, so all you need is to dive in. The way I suggest to do it
(apparently a path also followed by Jerry James <james@xemacs.org> in
XEmacs) does not require any special knowledge, AFAICT.
Just write a .c file and matching .h that will be included in Emacs and
that describe some functions exported from Emacs to the dynload modules.
Then adjust your libnettle code to use those exported functions instead
of the lisp.h macros. Then write a bit of package.el code that runs
a C compiler for packages that include such C files. And finally add
a `dynload' function that uses something along the lines of `dl_open'.
> but you already depend on libgnutls so I don't see what difference it
> makes here.
It means more code, hence more bugs to fix, especially in the long run.
It means more exposed interfaces that we'll have to live with for the
next decades.
Hence the need for "clear and concrete use-case" to justify the investment.
> the Emacs core well. I will make an effort here to list some use cases,
> but I am positive there will be more as time goes on. I would
> appreciate it if anyone else interested in this work added their use
> cases or vote of support.
I don't need hypothetical use-cases. I need concrete ones.
> - symmetric encryption without the burden or risk of shelling out
> (http://gnutls.org/manual/html_node/Encryption-algorithms-used-in-the-record-layer.html#tab_003aciphers).
> I would love to use this instead of the painfully heavy GnuPG
> integration for the symmetric case.
I don't see off hand what would be the benefit: maybe it avoids the
password problems you reported, but IIUC these only affect GPG2, so
there's already an alternative solution which is to use GPG1.
Also, it sounds like it wouldn't immediately give us the ability to
en/decrypt GPG messages, but instead we'd either have to roll our own
format (bad idea), or reimplement some of GPG's code (bad idea).
Better work on trying to solve the password problem either by fixing
GPG2 or by changing the way epg.el uses GPG2.
> - HMAC keyed hashing (http://www.ietf.org/rfc/rfc2104.txt) allowing
> message authentication with a shared key. For instance, that would
> allow the Emacs client and server to authenticate the data they share
> without a full PPK infrastructure,
Still requires distribution of that shared key, which seems like a pain
compared to simply connecting via SSH.
So, I'll be happy to add such code to GNU ELPA, but for now I don't want
it in Emacs. Hence the FFI.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Emacs crypto use cases
2013-10-08 3:02 ` Emacs crypto use cases Stefan Monnier
@ 2013-10-08 10:33 ` Ted Zlatanov
2013-10-08 13:17 ` Stephen J. Turnbull
2013-10-08 16:35 ` DSO-style FFI (was: Emacs crypto use cases) Stefan Monnier
0 siblings, 2 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-08 10:33 UTC (permalink / raw)
To: emacs-devel
On Mon, 07 Oct 2013 23:02:21 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> I can't help the FFI problem,
SM> Can't see why not. On the contrary, you have a perfect use case for the
SM> FFI, so all you need is to dive in. The way I suggest to do it
SM> (apparently a path also followed by Jerry James <james@xemacs.org> in
SM> XEmacs) does not require any special knowledge, AFAICT.
SM> Just write a .c file and matching .h that will be included in Emacs and
SM> that describe some functions exported from Emacs to the dynload modules.
SM> Then adjust your libnettle code to use those exported functions instead
SM> of the lisp.h macros. Then write a bit of package.el code that runs
SM> a C compiler for packages that include such C files. And finally add
SM> a `dynload' function that uses something along the lines of `dl_open'.
I have no idea how that would work. Is there an example? And is this
anywhere close to usable? The FFI discussion thread hasn't indicated
it. If I'm to be the guinea pig, I'm not excited about it.
>> but you already depend on libgnutls so I don't see what difference it
>> makes here.
SM> It means more code, hence more bugs to fix, especially in the long run.
SM> It means more exposed interfaces that we'll have to live with for the
SM> next decades.
SM> Hence the need for "clear and concrete use-case" to justify the
SM> investment.
I honestly didn't know Emacs was turning into Enterprise Software.
>> the Emacs core well. I will make an effort here to list some use cases,
>> but I am positive there will be more as time goes on. I would
>> appreciate it if anyone else interested in this work added their use
>> cases or vote of support.
SM> I don't need hypothetical use-cases. I need concrete ones.
>> - symmetric encryption without the burden or risk of shelling out
>> (http://gnutls.org/manual/html_node/Encryption-algorithms-used-in-the-record-layer.html#tab_003aciphers).
>> I would love to use this instead of the painfully heavy GnuPG
>> integration for the symmetric case.
SM> I don't see off hand what would be the benefit: maybe it avoids the
SM> password problems you reported, but IIUC these only affect GPG2, so
SM> there's already an alternative solution which is to use GPG1.
Given the choice between:
- run a persistent gpg-agent daemon everywhere and depend on it for
accessing my secret data, shelling out to GnuPG 2.x, installing it
everywhere I need my data
- shelling out to GnuPG 1.x, installing it everywhere I need my data
- calling a fast internal function against the existing GnuTLS libs
I prefer the last one. It may not be for everyone, but it's right for
me, and today we're *forcing* our users into a particular security model
away from the last choice.
In general I believe a well-integrated system is more reliable and
secure than a loosely coupled system, but the matter of choice is what
bothers me the most.
SM> Also, it sounds like it wouldn't immediately give us the ability to
SM> en/decrypt GPG messages, but instead we'd either have to roll our
SM> own format (bad idea), or reimplement some of GPG's code (bad idea).
As I mentioned, GnuTLS can provide most of that for us. The complicated
tricky parts are there; the OpenPGP protocol is mostly ASN decoding on
top. In any case, I hope this would be a ELPA package to remove it from
your concern.
SM> Better work on trying to solve the password problem either by fixing
SM> GPG2 or by changing the way epg.el uses GPG2.
I am tired of arguing that one, honestly. Comment on the relevant bugs
if you like, but right now there is no password problem according to
Daiki Ueno.
>> - HMAC keyed hashing (http://www.ietf.org/rfc/rfc2104.txt) allowing
>> message authentication with a shared key. For instance, that would
>> allow the Emacs client and server to authenticate the data they share
>> without a full PPK infrastructure,
SM> Still requires distribution of that shared key, which seems like a pain
SM> compared to simply connecting via SSH.
The distribution of a shared key enables *fast* message authentication
with minimal infrastructure. Setting up a separate SSH channel or PPK
or SSL certificates requires significant infrastructure.
(We could also require a private VLAN for every client-server
connection, that would be very secure and require no work from us. :)
SM> So, I'll be happy to add such code to GNU ELPA, but for now I don't want
SM> it in Emacs. Hence the FFI.
I'll see what I can do with FFI, but this is likely to take a lot of my
time. Some help getting started would go a long way.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Emacs crypto use cases
2013-10-08 10:33 ` Ted Zlatanov
@ 2013-10-08 13:17 ` Stephen J. Turnbull
2013-10-08 16:35 ` DSO-style FFI (was: Emacs crypto use cases) Stefan Monnier
1 sibling, 0 replies; 37+ messages in thread
From: Stephen J. Turnbull @ 2013-10-08 13:17 UTC (permalink / raw)
To: emacs-devel
Ted Zlatanov writes:
> SM> Just write a .c file and matching .h that will be included in Emacs and
> SM> that describe some functions exported from Emacs to the dynload modules.
> SM> Then adjust your libnettle code to use those exported functions instead
> SM> of the lisp.h macros. Then write a bit of package.el code that runs
> SM> a C compiler for packages that include such C files. And finally add
> SM> a `dynload' function that uses something along the lines of `dl_open'.
>
> I have no idea how that would work. Is there an example? And is this
> anywhere close to usable? The FFI discussion thread hasn't indicated
> it. If I'm to be the guinea pig, I'm not excited about it.
It's worked well in XEmacs since 2000. If you want to use our code
you'll need to get papers from J. Kean Johnston and Jerry James, and
maybe Ben Wing. I don't know how hard that will be, finding Kean
might be hard.
Jerry's been pretty busy recently, but he might be willing to give
advice if you go the roll-your-own route.
Steve
^ permalink raw reply [flat|nested] 37+ messages in thread
* DSO-style FFI (was: Emacs crypto use cases)
2013-10-08 10:33 ` Ted Zlatanov
2013-10-08 13:17 ` Stephen J. Turnbull
@ 2013-10-08 16:35 ` Stefan Monnier
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
2013-10-08 19:50 ` Ted Zlatanov
1 sibling, 2 replies; 37+ messages in thread
From: Stefan Monnier @ 2013-10-08 16:35 UTC (permalink / raw)
To: emacs-devel; +Cc: jerry.james
[ Hi Jerry. We're interested in adding support for dynamically loading
C code into Emacs, so I added you on the Cc, hoping you might be able
to give us some pointers to the XEmacs code, and maybe also some
guidance of things to watch out for. ]
> I have no idea how that would work. Is there an example?
As mentioned, there's the XEmacs implementation as an example.
> And is this anywhere close to usable?
Well, it doesn't exist for Emacs, so you won't be able to use until you
write it. AFAIK it's been usable for a decade in XEmacs.
> The FFI discussion thread hasn't indicated it.
There's no doubt it would work and it should be fairly flexible and
convenient for the implementer of lib<foo> wrapper. The main
inconvenients are in the area of imposing the use of a C compiler on the
user, and managing precompiled versions of the code, none of which seem
like reasons to make it "unusable".
> If I'm to be the guinea pig, I'm not excited about it.
No, you'd be the implementor, so you get to make it work well for you.
The guy that everyone after that will say "and finally, thanks to Ted,
we can now link to the new snazzy libquantum and solve all the Elisp
performance problems we had".
> I'll see what I can do with FFI, but this is likely to take a lot of my
> time. Some help getting started would go a long way.
Start as follows:
- take your lib<foo> wrapper.
- try to compile it outside of Emacs.
- for that you'll need a .h file that declares some functions like
`defsubr' and probably others to build and analyze Lisp data.
Ideally, this should not really too much on cpp macros and should not
make too many assumptions about the existing Emacs implementation, so
that this .h file doesn't need to change if/when we decide to tweak
the representation of Elisp data.
- write the .c file that should be linked into Emacs that provides the
functions declared in the magic .h file.
Now you should be able to build your "Emacs + lib<foo>" by simply
compiling your file and linking it into Emacs (i.e. pretty much like
what you have, except your lib-wrapper doesn't include lisp.h and such
but only the special new .h file you created).
That's step 1. It should be reasonably easy to do in terms of coding.
The design of the .h file is somewhat delicate, to try and avoid version
problems in the future, but we'll be happy to help along once you have
a first version of a .h.
Step 2: Write code that lets Emacs dynamically load the (compiled)
lib-wrapper code into a running Emacs, rather than having to provide
that lib-wrapper right when you link the `temacs' executable.
That shouldn't be hard either. One issue will be compatibility of
various kinds of dl_open mechanisms on various OSes, but you should find
lots of help for that here, so the first version can focus on supporting
only GNU/Linux. The other issue will be to make sure the loaded code is
GPL-compliant; we'll need help here anyway to know exactly what the FSF
wants in this regard but I don't foresee any serious issue.
At that point, you can start distributing your libnettle wrapper outside
of Emacs. Yay!
Step 3: provide helper infrastructure to distribute packages that use
this new functionality, e.g. teach package.el how to run the C compiler
on that code, stash the resulting compiled object somewhere, fetch
precompiled versions when a C compiler is not available, etc...
As you move forward, chances are more and more people will be motivated
to take on some of the work, so you don't have to do it all yourself.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 16:35 ` DSO-style FFI (was: Emacs crypto use cases) Stefan Monnier
@ 2013-10-08 17:32 ` Tom Tromey
2013-10-08 19:42 ` Ted Zlatanov
` (2 more replies)
2013-10-08 19:50 ` Ted Zlatanov
1 sibling, 3 replies; 37+ messages in thread
From: Tom Tromey @ 2013-10-08 17:32 UTC (permalink / raw)
To: Stefan Monnier; +Cc: jerry.james, emacs-devel
Stefan> Well, it doesn't exist for Emacs, so you won't be able to use until you
Stefan> write it. AFAIK it's been usable for a decade in XEmacs.
This approach seems very weird to me.
I don't understand why it is preferable to a libffi-based FFI.
The main difficulty I see is that now you're either promising an
internal Emacs ABI -- hard to do -- or you're requiring recompilations
whenever Emacs changes -- hard on users.
Stefan> One issue will be compatibility of various kinds of dl_open
Stefan> mechanisms on various OSes, but you should find lots of help for
Stefan> that here, so the first version can focus on supporting only
Stefan> GNU/Linux.
GNU already has libltdl.
Tom
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
@ 2013-10-08 19:42 ` Ted Zlatanov
2013-10-08 20:43 ` Tom Tromey
2013-10-08 20:47 ` Davis Herring
2013-10-09 1:48 ` DSO-style FFI Stephen J. Turnbull
2013-10-09 2:40 ` Stefan Monnier
2 siblings, 2 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-08 19:42 UTC (permalink / raw)
To: emacs-devel
On Tue, 08 Oct 2013 11:32:13 -0600 Tom Tromey <tromey@redhat.com> wrote:
Stefan> Well, it doesn't exist for Emacs, so you won't be able to use until you
Stefan> write it. AFAIK it's been usable for a decade in XEmacs.
Tom> This approach seems very weird to me.
Tom> I don't understand why it is preferable to a libffi-based FFI.
Tom> The main difficulty I see is that now you're either promising an
Tom> internal Emacs ABI -- hard to do -- or you're requiring recompilations
Tom> whenever Emacs changes -- hard on users.
Would any kind of FFI help with data formats? I don't think so, right?
The foreign function has to take Emacs Lisp_Objects (maybe just strings
and numbers) and package its return data in a Lisp_Object. So how do we
handle that glue with libffi or anything else without promising some
minimal internal Emacs ABI?
Stefan> One issue will be compatibility of various kinds of dl_open
Stefan> mechanisms on various OSes, but you should find lots of help for
Stefan> that here, so the first version can focus on supporting only
Stefan> GNU/Linux.
Tom> GNU already has libltdl.
I don't know much about libltdl but it seems fairly simple, except for
the requirement to name all exported symbols _modulename_LTX_* which is
a bit annoying.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 16:35 ` DSO-style FFI (was: Emacs crypto use cases) Stefan Monnier
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
@ 2013-10-08 19:50 ` Ted Zlatanov
1 sibling, 0 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-08 19:50 UTC (permalink / raw)
To: Stefan Monnier; +Cc: jerry.james, emacs-devel
On Tue, 08 Oct 2013 12:35:44 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
SM> [ Hi Jerry. We're interested in adding support for dynamically loading
SM> C code into Emacs, so I added you on the Cc, hoping you might be able
SM> to give us some pointers to the XEmacs code, and maybe also some
SM> guidance of things to watch out for. ]
>> I have no idea how that would work. Is there an example?
SM> As mentioned, there's the XEmacs implementation as an example.
Is 10-year-old glue code still the state of the art? Or should I be
using libffi and libltdl as Tom suggested? Or something else?
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 19:42 ` Ted Zlatanov
@ 2013-10-08 20:43 ` Tom Tromey
2013-10-09 23:21 ` Ted Zlatanov
2013-10-08 20:47 ` Davis Herring
1 sibling, 1 reply; 37+ messages in thread
From: Tom Tromey @ 2013-10-08 20:43 UTC (permalink / raw)
To: emacs-devel
Ted> Would any kind of FFI help with data formats? I don't think so, right?
Sure.
Basically you would need to expose "native" structures (and pointers and
whatnot) to elisp, so that elisp can manipulate their fields in various
ways. This is pretty easy to do; libffi doesn't provide code for this
specifically, but you can reuse the type descriptor stuff.
Ted> The foreign function has to take Emacs Lisp_Objects (maybe just strings
Ted> and numbers) and package its return data in a Lisp_Object. So how do we
Ted> handle that glue with libffi or anything else without promising some
Ted> minimal internal Emacs ABI?
The idea is to have the FFI code be part of Emacs. So when Emacs
changes, it does too. What doesn't change is the API presented to
elisp.
This is how FFI works in other languages -- Common Lisp, Python,
probably Guile (I didn't check), Java (it's part of reflection there),
etc.
Ted> I don't know much about libltdl but it seems fairly simple, except for
Ted> the requirement to name all exported symbols _modulename_LTX_* which is
Ted> a bit annoying.
I think that's only for preloaded modules.
Most people don't use this feature.
Tom
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 19:42 ` Ted Zlatanov
2013-10-08 20:43 ` Tom Tromey
@ 2013-10-08 20:47 ` Davis Herring
2013-10-09 22:26 ` Ted Zlatanov
1 sibling, 1 reply; 37+ messages in thread
From: Davis Herring @ 2013-10-08 20:47 UTC (permalink / raw)
To: emacs-devel
> Tom> This approach seems very weird to me.
> Tom> I don't understand why it is preferable to a libffi-based FFI.
> Tom> The main difficulty I see is that now you're either promising an
> Tom> internal Emacs ABI -- hard to do -- or you're requiring recompilations
> Tom> whenever Emacs changes -- hard on users.
>
> Would any kind of FFI help with data formats? I don't think so, right?
> The foreign function has to take Emacs Lisp_Objects (maybe just strings
> and numbers) and package its return data in a Lisp_Object. So how do we
> handle that glue with libffi or anything else without promising some
> minimal internal Emacs ABI?
An interface like ctypes from Python would not involve Lisp_Objects on
the other side, but would rather provide a means for a Lisp program to
specify a mapping from its objects (Lisp_Objects, of course) to the C
datatypes appropriate to the interface. Simple things like "expose my
string as a writable char*" and "copy my integer into an int passed by
value" would suffice for many clients (or many target libraries, which
is much the same thing). libffi helps to formulate the actual calls
(with all their platform/ABI-dependent nonsense) based on such abstract
descriptions.
Davis
--
This product is sold by volume, not by mass. If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
2013-10-08 19:42 ` Ted Zlatanov
@ 2013-10-09 1:48 ` Stephen J. Turnbull
2013-10-09 2:40 ` Stefan Monnier
2 siblings, 0 replies; 37+ messages in thread
From: Stephen J. Turnbull @ 2013-10-09 1:48 UTC (permalink / raw)
To: Tom Tromey; +Cc: emacs-devel, Stefan Monnier, jerry.james
Tom Tromey writes:
> I don't understand why it is preferable to a libffi-based FFI.
Offering dynamic loading only preserves the safety of the Lisp
language itself, modulo bugs in the called C code. An FFI done simply
will make it possible to write buggy Lisp code that crashes non-buggy
Emacs and/or non-buggy external libraries. Doing the FFI right is
very finicky and probably depends on the internals of libffi and
Emacs. As Ralph Nader put it, "unsafe at any speed".
> The main difficulty I see is that now you're either promising an
> internal Emacs ABI -- hard to do
Just for the subr calls. Modules aren't allowed to call ordinary
functions from Emacs, just DEFUNs.
> -- or you're requiring recompilations whenever Emacs changes --
> hard on users.
Perhaps. Worry about this, and the complete lack of demand from
non-developer users, is why XEmacs has never made DSOs part of the
package system.
> Stefan> One issue will be compatibility of various kinds of dl_open
> Stefan> mechanisms on various OSes, but you should find lots of help for
> Stefan> that here, so the first version can focus on supporting only
> Stefan> GNU/Linux.
>
> GNU already has libltdl.
I forget which one it is, but one of the dlopen mechanisms now works
on recent versions of all platforms XEmacs supports (I think even
native Windows).
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
2013-10-08 19:42 ` Ted Zlatanov
2013-10-09 1:48 ` DSO-style FFI Stephen J. Turnbull
@ 2013-10-09 2:40 ` Stefan Monnier
2013-10-12 15:34 ` Michael Welsh Duggan
2 siblings, 1 reply; 37+ messages in thread
From: Stefan Monnier @ 2013-10-09 2:40 UTC (permalink / raw)
To: Tom Tromey; +Cc: jerry.james, emacs-devel
> This approach seems very weird to me.
Yup.
> I don't understand why it is preferable to a libffi-based FFI.
I don't claim it's a better solution, really. I just don't see anny
movement towards providing libffi support (other than people saying we
should do it).
I think the reason is that I don't know anyone who's willing/able to add
libffi support to Emacs and write the corresponding code to link to
(say) libgnutls.
Whereas the path I suggest only involves steps which I'm pretty sure
many people here can do without much trouble.
Stefan> One issue will be compatibility of various kinds of dl_open
Stefan> mechanisms on various OSes, but you should find lots of help for
Stefan> that here, so the first version can focus on supporting only
Stefan> GNU/Linux.
> GNU already has libltdl.
See, "you should find lots of help for that here".
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 20:47 ` Davis Herring
@ 2013-10-09 22:26 ` Ted Zlatanov
2013-10-09 23:52 ` Davis Herring
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-09 22:26 UTC (permalink / raw)
To: emacs-devel
On Tue, 08 Oct 2013 14:47:17 -0600 Davis Herring <herring@lanl.gov> wrote:
DH> An interface like ctypes from Python would not involve Lisp_Objects on
DH> the other side, but would rather provide a means for a Lisp program to
DH> specify a mapping from its objects (Lisp_Objects, of course) to the C
DH> datatypes appropriate to the interface. Simple things like "expose my
DH> string as a writable char*" and "copy my integer into an int passed by
DH> value" would suffice for many clients (or many target libraries, which
DH> is much the same thing). libffi helps to formulate the actual calls
DH> (with all their platform/ABI-dependent nonsense) based on such abstract
DH> descriptions.
That's pretty dangerous, isn't it? Any memory corruption, intentional
or not, could affect the user significantly. Is that an acceptable risk?
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-08 20:43 ` Tom Tromey
@ 2013-10-09 23:21 ` Ted Zlatanov
2013-10-10 8:09 ` Andreas Schwab
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-09 23:21 UTC (permalink / raw)
To: emacs-devel
On Tue, 08 Oct 2013 14:43:39 -0600 Tom Tromey <tromey@redhat.com> wrote:
Ted> The foreign function has to take Emacs Lisp_Objects (maybe just strings
Ted> and numbers) and package its return data in a Lisp_Object. So how do we
Ted> handle that glue with libffi or anything else without promising some
Ted> minimal internal Emacs ABI?
Tom> The idea is to have the FFI code be part of Emacs. So when Emacs
Tom> changes, it does too. What doesn't change is the API presented to
Tom> elisp.
Tom> This is how FFI works in other languages -- Common Lisp, Python,
Tom> probably Guile (I didn't check), Java (it's part of reflection there),
Tom> etc.
It would really help if we discussed a small example, and forgive my
ignorance here.
Say I have a transforming function:
int gnutls_xform(char* datain, char* dataout);
I want to use a Lisp_Object, a string, for `datain'; and get back another
Lisp_Object, again a string, in `dataout'.
So, something like this would be done on a given function_pointer to
`gnutls_xform', with some given Lisp_Object `input_data':
ffi_cif cif;
ffi_type *args[2];
void *values[2];
char *in = SDATA (input_data);
char *out = xzmalloc(100);
int rc;
args[0] = &ffi_type_pointer;
values[0] = ∈
args[1] = &ffi_type_pointer;
values[1] = &out;
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_uint, args) == FFI_OK)
{
ffi_call(&cif, function_pointer, &rc, values);
/* rc now holds the result of the call */
}
Lisp_Object ret = Qnil;
// if rc shows success...
if (rc != ERROR)
{
ret = make_string (out);
}
xfree(out);
This would be more generic of course, but keeping it simple for now
really helps.
As far as the dynamic function loading to give us function_pointer, I am
guessing it's done with libltdl, by calling
module = lt_dlopen("emacs_gnutls_module");
and then
lt_dlsym(module, "gnutls_xform");
as shown in
http://www.gnu.org/software/libtool/manual/html_node/Libltdl-interface.html
Is that more or less where we should be going? Is this today's state of
the art? Based on the other languages you listed, it seems so.
My immediate concerns are security (these modules can do almost
anything); concurrency between modules and Emacs; and between modules
loaded by concurrent Emacs threads in a hypothetical future where we
have such threads. But in terms of practical integration they seem
workable.
Thanks for your patience
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-09 22:26 ` Ted Zlatanov
@ 2013-10-09 23:52 ` Davis Herring
2013-10-10 1:25 ` Ted Zlatanov
0 siblings, 1 reply; 37+ messages in thread
From: Davis Herring @ 2013-10-09 23:52 UTC (permalink / raw)
To: emacs-devel
> That's pretty dangerous, isn't it? Any memory corruption, intentional
> or not, could affect the user significantly. Is that an acceptable risk?
Intentional memory corruption is entirely beside the point -- you're
already planning to run whatever code the DSO provides with your current
security credentials. (You even already run DSO-specified code as soon
as you call dlopen().)
As for accidental corruption, you can at least protect your Lisp_Objects
by controlling how you copy data into and out of them. (Of course, a
wild pointer can corrupt absolutely anything, but you're not very likely
to be in an undesirable "Emacs appears functional but is confused" state.)
Davis
--
This product is sold by volume, not by mass. If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-09 23:52 ` Davis Herring
@ 2013-10-10 1:25 ` Ted Zlatanov
2013-10-10 4:36 ` DSO-style DSOs (this is NOT an FFI!) Stephen J. Turnbull
0 siblings, 1 reply; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-10 1:25 UTC (permalink / raw)
To: emacs-devel
On Wed, 09 Oct 2013 17:52:36 -0600 Davis Herring <herring@lanl.gov> wrote:
>> That's pretty dangerous, isn't it? Any memory corruption, intentional
>> or not, could affect the user significantly. Is that an acceptable risk?
DH> Intentional memory corruption is entirely beside the point -- you're
DH> already planning to run whatever code the DSO provides with your current
DH> security credentials. (You even already run DSO-specified code as soon
DH> as you call dlopen().)
OK.
DH> As for accidental corruption, you can at least protect your Lisp_Objects
DH> by controlling how you copy data into and out of them. (Of course, a
DH> wild pointer can corrupt absolutely anything, but you're not very likely
DH> to be in an undesirable "Emacs appears functional but is confused" state.)
Yeah, I was wondering how much can be done here, but I guess "not much."
Moreover, I was wondering whether the risk is acceptable. The other
extreme is to have some protocol to externally executed modules so
there's no chance of corruption; it's very inefficient but also much
less risky. I think it's safe to say the risk of DSOs is acceptable to
everyone, but wanted to be clear about it.
Thanks for explaining.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style DSOs (this is NOT an FFI!)
2013-10-10 1:25 ` Ted Zlatanov
@ 2013-10-10 4:36 ` Stephen J. Turnbull
0 siblings, 0 replies; 37+ messages in thread
From: Stephen J. Turnbull @ 2013-10-10 4:36 UTC (permalink / raw)
To: emacs-devel
Ted Zlatanov writes:
> DH> As for accidental corruption, you can at least protect your Lisp_Objects
> DH> by controlling how you copy data into and out of them.
DSOs are no different from any other C code as far as data corruption
goes. You can't do anything more, and shouldn't do less, than you
could do if the code were linked into Emacs at build time. The advice
is "be a good Emacs C-level programmer, and you'll be OK."
The only reasonable restrictions are:
(1) Initialize the module with
if (this_module_max_gpl < this_emacs_min_gpl) launch_lawyers();
(if this_module_max_gpl is undefined, the link will fail, which is the
desired outcome :-).
(2) callbacks into Emacs must refer to symbols obtained from
intern(). You can't call extern functions or reference extern
variables directly.
The marshalling and unmarshalling implied by (2) needs to be done
anyway because these DSOs are intended to provide Lisp-level
functionality. (If not, there's no problem. Ask Eli Z about how
Windows does its "if-available" DLL loading.) It may as well be done
in the DSO so that intern() is the only rendezvous point needed
between Emacs and the DSO.
> Moreover, I was wondering whether the risk is acceptable.
If it's not, the implications for using any Emacs coded in C are,
well, *severe*. ;-) (The "maybe we're loading non-GPL 3d-party code
unknowingly" risk is an exception, of course. That's irrelevant to
language though -- I've always wondered why non-GPL DSOs are a risk
and non-GPL Lisp isn't. But let's not go there.... :-)
> The other extreme is to have some protocol to externally executed
> modules so there's no chance of corruption; it's very inefficient
> but also much less risky.
That may as well be a true FFI (ie, a way to bind Lisp symbols to
external objects from Lisp). If it's not, then the module programmer
is writing C, so: GOTO "DSOs are no different...."[1]
Footnotes:
[1] Emacs programmers are hardly exempt from the dictum "premature
optimization is the root of all error". The temptation to short cut
the protocol when writing C will be unbearable for some.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-09 23:21 ` Ted Zlatanov
@ 2013-10-10 8:09 ` Andreas Schwab
0 siblings, 0 replies; 37+ messages in thread
From: Andreas Schwab @ 2013-10-10 8:09 UTC (permalink / raw)
To: emacs-devel
Ted Zlatanov <tzz@lifelogs.com> writes:
> if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
> &ffi_type_uint, args) == FFI_OK)
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
&ffi_type_int, args) == FFI_OK)
Andreas.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-09 2:40 ` Stefan Monnier
@ 2013-10-12 15:34 ` Michael Welsh Duggan
2013-10-12 18:55 ` Stefan Monnier
2013-10-12 23:36 ` Stephen J. Turnbull
0 siblings, 2 replies; 37+ messages in thread
From: Michael Welsh Duggan @ 2013-10-12 15:34 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Tom Tromey, jerry.james, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> This approach seems very weird to me.
>
> Yup.
>
>> I don't understand why it is preferable to a libffi-based FFI.
>
> I don't claim it's a better solution, really. I just don't see anny
> movement towards providing libffi support (other than people saying we
> should do it).
>
> I think the reason is that I don't know anyone who's willing/able to add
> libffi support to Emacs and write the corresponding code to link to
> (say) libgnutls.
It seems to me that writing libffi support to Emacs isn't that difficult
in and of itself. I have no doubt that I could hack in something
low-level without too much difficulty. The problems I see are A) that
it would be trivial to use such an interface to crash or subvert emacs
from elisp, and B) that such a binding will allow people to write
non-free extensions to Emacs in just the way that RMS has specifically
stated that he would like to avoid.
As an example, it would be possible to use a raw libffi binding to call
memset with appropriate arguments to tromp right over any memory that
emacs has access to.
This isn't to say that something that is not libffi itself could use
libffi to create something safer. Though I don't know what that would
be.
--
Michael Welsh Duggan
(md5i@md5i.com)
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-12 15:34 ` Michael Welsh Duggan
@ 2013-10-12 18:55 ` Stefan Monnier
2013-10-18 13:31 ` Ted Zlatanov
2013-10-12 23:36 ` Stephen J. Turnbull
1 sibling, 1 reply; 37+ messages in thread
From: Stefan Monnier @ 2013-10-12 18:55 UTC (permalink / raw)
To: Michael Welsh Duggan; +Cc: Tom Tromey, jerry.james, emacs-devel
> It seems to me that writing libffi support to Emacs isn't that difficult
> in and of itself. I have no doubt that I could hack in something
> low-level without too much difficulty.
Could be. I haven't seen anything concrete (and of course, providing
access to libffi is only one half of the problem, the other half is to
write the binding to lib<foo>, and my impression is that more
people would know how to do that if that part were written in C).
> The problems I see are A) that it would be trivial to use such an
> interface to crash or subvert emacs from elisp,
This is a fundamental property of anything that lets gives access to
"any" library. DSO or FFI is in the same boat. IOW, if we really
consider it as too dangerous, then we can't provide anything related to
an FFI or dynamic loading of code.
> and B) that such a binding will allow people to write non-free
> extensions to Emacs in just the way that RMS has specifically stated
> that he would like to avoid.
Presumably we can prevent it by checking (before loading the library)
that the library is compatible with the GPL (following the scheme
designed originally for gcc).
> This isn't to say that something that is not libffi itself could use
> libffi to create something safer.
Don't worry: as long as you want to be able to link libraries written in
languages like C, you can't make it safer.
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-12 15:34 ` Michael Welsh Duggan
2013-10-12 18:55 ` Stefan Monnier
@ 2013-10-12 23:36 ` Stephen J. Turnbull
1 sibling, 0 replies; 37+ messages in thread
From: Stephen J. Turnbull @ 2013-10-12 23:36 UTC (permalink / raw)
To: Michael Welsh Duggan; +Cc: Tom Tromey, emacs-devel, Stefan Monnier, jerry.james
Michael Welsh Duggan writes:
> As an example, it would be possible to use a raw libffi binding to call
> memset with appropriate arguments to tromp right over any memory that
> emacs has access to.
Sure. But this requires a bit of knowledge of C APIs. With a tiny
bit more knowledge of C and a dollop of cargo cult, one can use
Stefan's interface to do the same thing, compile it, load it, and
crash or corrupt Emacs. One could even write Lisp that writes most of
such a program.
> This isn't to say that something that is not libffi itself could
> use libffi to create something safer.
No, you can't, in practice. That would require all libraries to be
safely coded (in the sense that memset is not). You would need to
exclude linkage to unsafe APIs, but that would be very hard to do (how
about calling PNG editing facilities on an uninitialized piece of
memory that happens to already contain Emacs code or data?)
As for RMS's freedom concern, he's already stated what would be
acceptable: create an Emacs-side API requirement in its FFI
implementation that the DSO declare its GPL compatibility (including
version, I assume). If the API isn't present, dlopen() will fail,
AIUI. If the API doesn't declare a compatible set of versions, the
FFI implementation will refuse to bind Lisp to the DSO and unload it.
Note that this is actually quite effective as far as I can see. If a
DSO is being commercially distributed under false pretenses at the API
level, that's not just a copyright violation, it's fraud. This means
that there's a good chance that not only the FSF (as owner of the
copyright to Emacs), but also the customer (victim of fraud) and the
relevant government authorities (since fraud is a crime) have standing
to take action against the perpetrator. (Copyright violation in
general is a tort, not a crime, so the FSF as owner needs to take
action.) IANAL, etc, but if RMS and the FSF's legal staff are in
agreement that this is good enough, I'm willing to bet it is. :-)
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-12 18:55 ` Stefan Monnier
@ 2013-10-18 13:31 ` Ted Zlatanov
2013-10-19 14:41 ` Stefan Monnier
` (2 more replies)
0 siblings, 3 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-18 13:31 UTC (permalink / raw)
To: emacs-devel
On Sat, 12 Oct 2013 14:55:26 -0400 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote:
>> The problems I see are A) that it would be trivial to use such an
>> interface to crash or subvert emacs from elisp,
SM> This is a fundamental property of anything that lets gives access to
SM> "any" library. DSO or FFI is in the same boat. IOW, if we really
SM> consider it as too dangerous, then we can't provide anything related to
SM> an FFI or dynamic loading of code.
This is where package signing becomes important. We can require two
signatures from two separate reviewers for high-risk packages.
>> and B) that such a binding will allow people to write non-free
>> extensions to Emacs in just the way that RMS has specifically stated
>> that he would like to avoid.
SM> Presumably we can prevent it by checking (before loading the library)
SM> that the library is compatible with the GPL (following the scheme
SM> designed originally for gcc).
This can be declared by the author in the packaging. Do we need to spend
time on an elaborate scheme that can be trivially subverted? Or are
there other concerns I'm not getting?
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-18 13:31 ` Ted Zlatanov
@ 2013-10-19 14:41 ` Stefan Monnier
2013-10-19 15:08 ` Stefan Monnier
2013-10-19 17:33 ` Andy Moreton
2 siblings, 0 replies; 37+ messages in thread
From: Stefan Monnier @ 2013-10-19 14:41 UTC (permalink / raw)
To: emacs-devel
>>>>> "Ted" == Ted Zlatanov <tzz@lifelogs.com> writes:
> On Sat, 12 Oct 2013 14:55:26 -0400 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote:
>>> The problems I see are A) that it would be trivial to use such an
>>> interface to crash or subvert emacs from elisp,
SM> This is a fundamental property of anything that lets gives access to
SM> "any" library. DSO or FFI is in the same boat. IOW, if we really
SM> consider it as too dangerous, then we can't provide anything related to
SM> an FFI or dynamic loading of code.
> This is where package signing becomes important. We can require two
> signatures from two separate reviewers for high-risk packages.
>>> and B) that such a binding will allow people to write non-free
>>> extensions to Emacs in just the way that RMS has specifically stated
>>> that he would like to avoid.
SM> Presumably we can prevent it by checking (before loading the library)
SM> that the library is compatible with the GPL (following the scheme
SM> designed originally for gcc).
> This can be declared by the author in the packaging. Do we need to spend
> time on an elaborate scheme that can be trivially subverted? Or are
> there other concerns I'm not getting?
> Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-18 13:31 ` Ted Zlatanov
2013-10-19 14:41 ` Stefan Monnier
@ 2013-10-19 15:08 ` Stefan Monnier
2013-10-19 17:33 ` Andy Moreton
2 siblings, 0 replies; 37+ messages in thread
From: Stefan Monnier @ 2013-10-19 15:08 UTC (permalink / raw)
To: emacs-devel
SM> This is a fundamental property of anything that lets gives access to
SM> "any" library. DSO or FFI is in the same boat. IOW, if we really
SM> consider it as too dangerous, then we can't provide anything related to
SM> an FFI or dynamic loading of code.
> This is where package signing becomes important.
More or less. I mean, yes, it's annoying when Emacs crashes, but in
terms of security, being able to run arbitrary C code is not really
worse than being able to run arbitrary Elisp code, and in terms of
reliability, Elisp code can also render your Emacs unusable (without
crashing it).
SM> Presumably we can prevent it by checking (before loading the library)
SM> that the library is compatible with the GPL (following the scheme
SM> designed originally for gcc).
> This can be declared by the author in the packaging. Do we need to spend
> time on an elaborate scheme that can be trivially subverted? Or are
> there other concerns I'm not getting?
As someone else explained, the issue is not whether subverting it is
hard, but rather whether subverting it must be done in a blatant-enough
way that it makes a difference, from a legal point of view (e.g. it
turns into fraud, rather than mere copyright violation).
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-18 13:31 ` Ted Zlatanov
2013-10-19 14:41 ` Stefan Monnier
2013-10-19 15:08 ` Stefan Monnier
@ 2013-10-19 17:33 ` Andy Moreton
2013-10-19 19:44 ` Ted Zlatanov
2 siblings, 1 reply; 37+ messages in thread
From: Andy Moreton @ 2013-10-19 17:33 UTC (permalink / raw)
To: emacs-devel
On Fri 18 Oct 2013, Ted Zlatanov wrote:
> On Sat, 12 Oct 2013 14:55:26 -0400 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote:
>
>>> The problems I see are A) that it would be trivial to use such an
>>> interface to crash or subvert emacs from elisp,
>
> SM> This is a fundamental property of anything that lets gives access to
> SM> "any" library. DSO or FFI is in the same boat. IOW, if we really
> SM> consider it as too dangerous, then we can't provide anything related to
> SM> an FFI or dynamic loading of code.
>
> This is where package signing becomes important. We can require two
> signatures from two separate reviewers for high-risk packages.
Package signing is not really relevant here: knowing who signed a
package does not magically prevent emacs from crashing. If you want to
prevent crashes, then you need to isolate the third party code by
running it in a separate process.
AndyM
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: DSO-style FFI
2013-10-19 17:33 ` Andy Moreton
@ 2013-10-19 19:44 ` Ted Zlatanov
0 siblings, 0 replies; 37+ messages in thread
From: Ted Zlatanov @ 2013-10-19 19:44 UTC (permalink / raw)
To: emacs-devel
On Sat, 19 Oct 2013 18:33:27 +0100 Andy Moreton <andrewjmoreton@gmail.com> wrote:
AM> On Fri 18 Oct 2013, Ted Zlatanov wrote:
>> On Sat, 12 Oct 2013 14:55:26 -0400 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote:
>>
>>>> The problems I see are A) that it would be trivial to use such an
>>>> interface to crash or subvert emacs from elisp,
>>
SM> This is a fundamental property of anything that lets gives access to
SM> "any" library. DSO or FFI is in the same boat. IOW, if we really
SM> consider it as too dangerous, then we can't provide anything related to
SM> an FFI or dynamic loading of code.
>>
>> This is where package signing becomes important. We can require two
>> signatures from two separate reviewers for high-risk packages.
AM> Package signing is not really relevant here: knowing who signed a
AM> package does not magically prevent emacs from crashing. If you want to
AM> prevent crashes, then you need to isolate the third party code by
AM> running it in a separate process.
A separate process doesn't guarantee safety either, depending on the
platform and the process owner.
Double signing would require two independent reviewers to sign off on
the package release. This gives some assurance that the code is not
apparently or intentionally harmful by not-so-magical means.
Ted
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2013-10-19 19:44 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-06 9:15 GNU Emacs-libnettle-libhogweed integration patch v1 Ted Zlatanov
2013-10-06 9:58 ` bignum support in Emacs with libgmp (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
2013-10-06 16:09 ` GNU Emacs-libnettle-libhogweed integration patch v1 Eli Zaretskii
2013-10-06 21:07 ` Ted Zlatanov
2013-10-06 16:51 ` Stefan Monnier
2013-10-06 16:58 ` Eli Zaretskii
2013-10-06 21:19 ` Ted Zlatanov
2013-10-07 4:02 ` Stefan Monnier
2013-10-07 11:41 ` Ted Zlatanov
2013-10-07 22:03 ` Ted Zlatanov
2013-10-07 22:58 ` Stefan Monnier
2013-10-07 23:43 ` Emacs crypto use cases (was: GNU Emacs-libnettle-libhogweed integration patch v1) Ted Zlatanov
2013-10-08 3:02 ` Emacs crypto use cases Stefan Monnier
2013-10-08 10:33 ` Ted Zlatanov
2013-10-08 13:17 ` Stephen J. Turnbull
2013-10-08 16:35 ` DSO-style FFI (was: Emacs crypto use cases) Stefan Monnier
2013-10-08 17:32 ` DSO-style FFI Tom Tromey
2013-10-08 19:42 ` Ted Zlatanov
2013-10-08 20:43 ` Tom Tromey
2013-10-09 23:21 ` Ted Zlatanov
2013-10-10 8:09 ` Andreas Schwab
2013-10-08 20:47 ` Davis Herring
2013-10-09 22:26 ` Ted Zlatanov
2013-10-09 23:52 ` Davis Herring
2013-10-10 1:25 ` Ted Zlatanov
2013-10-10 4:36 ` DSO-style DSOs (this is NOT an FFI!) Stephen J. Turnbull
2013-10-09 1:48 ` DSO-style FFI Stephen J. Turnbull
2013-10-09 2:40 ` Stefan Monnier
2013-10-12 15:34 ` Michael Welsh Duggan
2013-10-12 18:55 ` Stefan Monnier
2013-10-18 13:31 ` Ted Zlatanov
2013-10-19 14:41 ` Stefan Monnier
2013-10-19 15:08 ` Stefan Monnier
2013-10-19 17:33 ` Andy Moreton
2013-10-19 19:44 ` Ted Zlatanov
2013-10-12 23:36 ` Stephen J. Turnbull
2013-10-08 19:50 ` Ted Zlatanov
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).