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