unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* 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

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).