From 24f3cce7bca7f58cb0eb9eff7674d3c0f9302538 Mon Sep 17 00:00:00 2001
From: Simon Josefsson <simon@josefsson.org>
Date: Wed, 19 Sep 2012 22:55:06 +0200
Subject: [PATCH] Support for pbkdf2.

---
 ChangeLog                  | 17 +++++++
 Makefile.in                |  2 +
 NEWS                       |  7 +++
 nettle.texinfo             | 43 ++++++++++++++++-
 pbkdf2.c                   | 94 ++++++++++++++++++++++++++++++++++++++
 pbkdf2.h                   | 60 ++++++++++++++++++++++++
 testsuite/.gitignore       |  1 +
 testsuite/.test-rules.make |  3 ++
 testsuite/Makefile.in      |  2 +-
 9 files changed, 226 insertions(+), 3 deletions(-)
 create mode 100644 pbkdf2.c
 create mode 100644 pbkdf2.h

diff --git a/ChangeLog b/ChangeLog
index f2a20100..7fca2a2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2012-09-19  Niels Möller  <nisse@lysator.liu.se>
+
+	* pbkdf2.h (PBKDF2): New macro.
+	* testsuite/pbkdf2-test.c: Use it.
+
+2012-09-12  Simon Josefsson  <simon@josefsson.org>
+
+	* NEWS: Mention addition of PBKDF2.
+	* pbkdf2.c (pbkdf2): New file and function.
+	* pbkdf2.h: Declare it.
+	* Makefile.in (nettle_SOURCES): Add pbkdf2.c.
+	(HEADERS): Add pbkdf2.h.
+	* nettle.texinfo (Key derivation functions): New section.
+	* testsuite/pbkdf2-test.c: New test case.
+	* testsuite/Makefile.in (TS_NETTLE_SOURCES): Add pbkdf2-test.c.
+	* testsuite/.test-rules.make (pbkdf2-test): New target.
+
 2012-09-16  Niels Möller  <nisse@lysator.liu.se>
 
 	* testsuite/: Overhaul of testsuite, affecting almost all files.
diff --git a/Makefile.in b/Makefile.in
index cf935939..7c6cf337 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -77,6 +77,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 des3.c des-compat.c \
 		 hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
 		 hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
+		 pbkdf2.c \
 		 knuth-lfib.c \
 		 md2.c md2-meta.c md4.c md4-meta.c \
 		 md5.c md5-compress.c md5-compat.c md5-meta.c \
@@ -123,6 +124,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
 	  cbc.h ctr.h gcm.h \
 	  des.h des-compat.h dsa.h \
 	  hmac.h \
+	  pbkdf2.h \
 	  knuth-lfib.h \
 	  macros.h \
 	  md2.h md4.h \
diff --git a/NEWS b/NEWS
index 4957f80e..8f7e9e67 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+NEWS for the 2.6 release
+
+	New features:
+
+	* Support for PKCS #5 PBKDF2.  Contributed by Simon Josefsson.
+          Specification in RFC 2898 and test vectors in RFC 6070.
+
 NEWS for the 2.5 release
 
 	This release includes important portability fixes for Windows
diff --git a/nettle.texinfo b/nettle.texinfo
index 4904d91a..39f3c68b 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -70,6 +70,7 @@ Reference
 * Cipher functions::            
 * Cipher modes::                
 * Keyed hash functions::        
+* Key derivation functions::    
 * Public-key algorithms::       
 * Randomness::                  
 * Ascii encoding::              
@@ -199,6 +200,10 @@ implementation (in the public domain), adapted to Nettle by Simon
 Josefsson, and heavily modified by Niels Möller. Assembly for x86_64 by
 Niels Möller. Released under the LGPL.
 
+@item PBKDF2
+The C implementation of PBKDF2 is based on earlier work for Shishi and
+GnuTLS by Simon Josefsson.  Released under the LGPL.
+
 @item SERPENT
 The implementation of the SERPENT cipher is based on the code in libgcrypt,
 copyright owned by the Free Software Foundation. Adapted to Nettle by
@@ -316,6 +321,7 @@ This chapter describes all the Nettle functions, grouped by family.
 * Cipher functions::            
 * Cipher modes::                
 * Keyed hash functions::        
+* Key derivation functions::    
 * Public-key algorithms::       
 * Randomness::                  
 * Ascii encoding::              
@@ -1852,7 +1858,7 @@ only the first @var{length} octets of the digest are written.
 
 
 
-@node Keyed hash functions, Public-key algorithms, Cipher modes, Reference
+@node Keyed hash functions, Key derivation functions, Cipher modes, Reference
 @comment  node-name,  next,  previous,  up
 @section Keyed Hash Functions
 
@@ -2102,7 +2108,40 @@ This function also resets the context for processing new messages, with
 the same key.
 @end deftypefun
 
-@node Public-key algorithms, Randomness, Keyed hash functions, Reference
+@node Key derivation functions, Public-key algorithms, Keyed hash functions, Reference
+@comment  node-name,  next,  previous,  up
+@section Key derivation Functions
+
+@cindex Key Derivation Function
+@cindex Password Based Key Derivation Function
+@cindex PKCS #5
+@cindex KDF
+@cindex PBKDF
+
+A @dfn{key derivation function} (@acronym{KDF}) is a function that from
+a given symmetric key derives other symmetric keys.  A sub-class of KDFs
+is the @dfn{password-based key derivation functions} (@acronym{PBKDFs}),
+which take as input a password or passphrase, and its purpose is
+typically to strengthen it and protect against certain pre-computation
+attacks by using salting and expensive computation.  The most well known
+PBKDF is the @code{PKCS #5 PBKDF2} described in @cite{RFC 2898} which
+uses a pseudorandom function such as @acronym{HMAC-SHA1}.
+
+Nettle's @acronym{PBKDF2} function is defined in @file{<nettle/pbkdf2.h>}.
+It contains a function:
+
+@deftypefun void pbkdf2 (void *mac_ctx, unsigned digest_size, nettle_hash_update_func *update, nettle_hash_digest_func *digest, unsigned length, uint8_t *dst, unsigned iterations, unsigned salt_length, const uint8_t *salt)
+Derive symmetric key from a password according to PKCS #5 PBKDF2.  The
+PRF is assumed to have been initialized and this function will call the
+@var{update} and @var{digest} functions passing the @var{mac_ctx}
+context parameter as an argument in order to compute digest of size
+@var{digest_size}.  Inputs are the salt @var{salt} of length
+@var{salt_length}, the iteration counter @var{iterations} (> 0), and the
+desired derived output length @var{length}.  The output buffer is
+@var{dst} which must have room for at least @var{length} octets.
+@end deftypefun
+
+@node Public-key algorithms, Randomness, Key derivation functions, Reference
 @comment  node-name,  next,  previous,  up
 @section Public-key algorithms
 
diff --git a/pbkdf2.c b/pbkdf2.c
new file mode 100644
index 00000000..e70c3017
--- /dev/null
+++ b/pbkdf2.c
@@ -0,0 +1,94 @@
+/* pbkdf2.c
+ *
+ * PKCS #5 password-based key derivation function PBKDF2, see RFC 2898.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2012 Simon Josefsson
+ *
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The nettle library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pbkdf2.h"
+
+#include "macros.h"
+#include "memxor.h"
+#include "nettle-internal.h"
+
+void
+pbkdf2 (void *mac_ctx, unsigned digest_size,
+	nettle_hash_update_func *update,
+	nettle_hash_digest_func *digest,
+	unsigned length, uint8_t *dst,
+	unsigned iterations,
+	unsigned salt_length, const uint8_t *salt)
+{
+  TMP_DECL(U, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+  TMP_DECL(T, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+  
+  unsigned int u;
+  unsigned int l;
+  unsigned int r;
+  unsigned int i;
+  char tmp[4];
+
+  if (iterations == 0)
+    return;
+
+  if (length == 0)
+    return;
+
+  l = ((length - 1) / digest_size) + 1;
+  r = length - (l - 1) * digest_size;
+
+  TMP_ALLOC (U, digest_size);
+  TMP_ALLOC (T, digest_size);
+
+  for (i = 1; i <= l; i++)
+    {
+      memset (T, 0, digest_size);
+
+      for (u = 1; u <= iterations; u++)
+	{
+	  if (u == 1)
+	    {
+	      WRITE_UINT32 (tmp, i);
+
+	      update (mac_ctx, salt_length, salt);
+	      update (mac_ctx, 4, tmp);
+	    }
+	  else
+	    {
+	      update (mac_ctx, digest_size, U);
+	    }
+
+	  digest (mac_ctx, digest_size, U);
+
+	  memxor (T, U, digest_size);
+	}
+
+      memcpy (dst + (i - 1) * digest_size, T, i == l ? r : digest_size);
+    }
+}
diff --git a/pbkdf2.h b/pbkdf2.h
new file mode 100644
index 00000000..59719ae1
--- /dev/null
+++ b/pbkdf2.h
@@ -0,0 +1,60 @@
+/* pbkdf2.c
+ *
+ * PKCS #5 password-based key derivation function PBKDF2, see RFC 2898.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2012 Simon Josefsson
+ *
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The nettle library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#ifndef NETTLE_PBKDF2_H_INCLUDED
+#define NETTLE_PBKDF2_H_INCLUDED
+
+#include "nettle-meta.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define pbkdf2 nettle_pbkdf2
+
+void
+pbkdf2 (void *mac_ctx, unsigned digest_size,
+	nettle_hash_update_func *update,
+	nettle_hash_digest_func *digest,
+	unsigned length, uint8_t *dst,
+	unsigned iterations,
+	unsigned salt_length, const uint8_t *salt);
+
+#define PBKDF2(ctx, digest_size, update, digest,			\
+	       length, dst, iterations, salt_length, salt)		\
+  (0 ? ((update)((ctx), 0, (const uint8_t *) 0),			\
+	(digest)((ctx), 0, (uint8_t *) 0))				\
+   : pbkdf2 ((ctx), (digest_size),					\
+	     (nettle_hash_update_func *)(update),			\
+	     (nettle_hash_digest_func *)(digest),			\
+	     (length), (dst), (iterations), (salt_length), (salt)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_PBKDF2_H_INCLUDED */
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index c9f46987..783c9f5d 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -29,6 +29,7 @@
 /meta-armor-test
 /meta-cipher-test
 /meta-hash-test
+/pbkdf2-test
 /pkcs1-test
 /random-prime-test
 /ripemd160-test
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index 10c993f8..d8f8f23a 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -88,6 +88,9 @@ gcm-test$(EXEEXT): gcm-test.$(OBJEXT)
 hmac-test$(EXEEXT): hmac-test.$(OBJEXT)
 	$(LINK) hmac-test.$(OBJEXT) $(TEST_OBJS) -o hmac-test$(EXEEXT)
 
+pbkdf2-test$(EXEEXT): pbkdf2-test.$(OBJEXT)
+	$(LINK) pbkdf2-test.$(OBJEXT) $(TEST_OBJS) -o pbkdf2-test$(EXEEXT)
+
 meta-hash-test$(EXEEXT): meta-hash-test.$(OBJEXT)
 	$(LINK) meta-hash-test.$(OBJEXT) $(TEST_OBJS) -o meta-hash-test$(EXEEXT)
 
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 206a76e5..86f365a6 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -25,7 +25,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
 		    knuth-lfib-test.c \
 		    cbc-test.c ctr-test.c gcm-test.c hmac-test.c \
 		    meta-hash-test.c meta-cipher-test.c meta-armor-test.c \
-		    buffer-test.c yarrow-test.c
+		    buffer-test.c yarrow-test.c pbkdf2-test.c
 
 TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
 		     rsa2sexp-test.c sexp2rsa-test.c \
-- 
GitLab