On 03/18/2016 12:53 AM, Daniel P. Berrange wrote: > The LUKS data format includes use of PBKDF2 (Password-Based > Key Derivation Function). The Nettle library can provide > an implementation of this, but we don't want code directly > depending on a specific crypto library backend. Introduce > a new include/crypto/pbkdf.h header which defines a QEMU > API for invoking PBKDK2. The initial implementations are > backed by nettle & gcrypt, which are commonly available > with distros shipping GNUTLS. > > The test suite data is taken from the cryptsetup codebase > under the LGPLv2.1+ license. This merely aims to verify > that whatever backend we provide for this function in QEMU > will comply with the spec. > > Reviewed-by: Fam Zheng <f...@redhat.com> > Reviewed-by: Eric Blake <ebl...@redhat.com> > Signed-off-by: Daniel P. Berrange <berra...@redhat.com> > --- > configure | 18 +++ > crypto/Makefile.objs | 4 + > crypto/pbkdf-gcrypt.c | 68 ++++++++ > crypto/pbkdf-nettle.c | 65 ++++++++ > crypto/pbkdf-stub.c | 42 +++++ > crypto/pbkdf.c | 109 +++++++++++++ > include/crypto/pbkdf.h | 152 ++++++++++++++++++ > tests/.gitignore | 1 + > tests/Makefile | 2 + > tests/test-crypto-pbkdf.c | 392 > ++++++++++++++++++++++++++++++++++++++++++++++ > 10 files changed, 853 insertions(+) > create mode 100644 crypto/pbkdf-gcrypt.c > create mode 100644 crypto/pbkdf-nettle.c > create mode 100644 crypto/pbkdf-stub.c > create mode 100644 crypto/pbkdf.c > create mode 100644 include/crypto/pbkdf.h > create mode 100644 tests/test-crypto-pbkdf.c > > diff --git a/configure b/configure > index 71c1e2b..b88d0db 100755 > --- a/configure > +++ b/configure > @@ -309,6 +309,7 @@ gnutls_hash="" > gnutls_rnd="" > nettle="" > gcrypt="" > +gcrypt_kdf="no" > vte="" > virglrenderer="" > tpm="yes" > @@ -2302,6 +2303,19 @@ if test "$gcrypt" != "no"; then > if test -z "$nettle"; then > nettle="no" > fi > + > + cat > $TMPC << EOF > +#include <gcrypt.h> > +int main(void) { > + gcry_kdf_derive(NULL, 0, GCRY_KDF_PBKDF2, > + GCRY_MD_SHA256, > + NULL, 0, 0, 0, NULL); > + return 0; > +} > +EOF > + if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then > + gcrypt_kdf=yes > + fi > else > if test "$gcrypt" = "yes"; then > feature_not_found "gcrypt" "Install gcrypt devel" > @@ -4726,6 +4740,7 @@ echo "GNUTLS support $gnutls" > echo "GNUTLS hash $gnutls_hash" > echo "GNUTLS rnd $gnutls_rnd" > echo "libgcrypt $gcrypt" > +echo "libgcrypt kdf $gcrypt_kdf" > if test "$nettle" = "yes"; then > echo "nettle $nettle ($nettle_version)" > else > @@ -5108,6 +5123,9 @@ if test "$gnutls_rnd" = "yes" ; then > fi > if test "$gcrypt" = "yes" ; then > echo "CONFIG_GCRYPT=y" >> $config_host_mak > + if test "$gcrypt_kdf" = "yes" ; then > + echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak > + fi > fi > if test "$nettle" = "yes" ; then > echo "CONFIG_NETTLE=y" >> $config_host_mak > diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs > index 967418c..7122cc8 100644 > --- a/crypto/Makefile.objs > +++ b/crypto/Makefile.objs > @@ -10,8 +10,12 @@ crypto-obj-y += tlssession.o > crypto-obj-y += secret.o > crypto-obj-$(CONFIG_GCRYPT) += random-gcrypt.o > crypto-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS_RND)) += random-gnutls.o > +crypto-obj-y += pbkdf.o > +crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o > +crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT_KDF)) += pbkdf-gcrypt.o > > # Let the userspace emulators avoid linking gnutls/etc > crypto-aes-obj-y = aes.o > > stub-obj-y += random-stub.o > +stub-obj-y += pbkdf-stub.o > diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c > new file mode 100644 > index 0000000..885614d > --- /dev/null > +++ b/crypto/pbkdf-gcrypt.c > @@ -0,0 +1,68 @@ > +/* > + * QEMU Crypto PBKDF support (Password-Based Key Derivation Function) > + * > + * Copyright (c) 2015-2016 Red Hat, Inc. > + * > + * This 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 of the License, or (at your option) any later version. > + * > + * This 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 this library; if not, see > <http://www.gnu.org/licenses/>. > + * > + */ > + > +#include "qemu/osdep.h" > +#include "crypto/pbkdf.h" > +#include "gcrypt.h" > + > +bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) > +{ > + switch (hash) { > + case QCRYPTO_HASH_ALG_MD5: > + case QCRYPTO_HASH_ALG_SHA1: > + case QCRYPTO_HASH_ALG_SHA256: > + return true; > + default: > + return false; > + } > +} > + > +int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, > + const uint8_t *key, size_t nkey, > + const uint8_t *salt, size_t nsalt, > + unsigned int iterations, > + uint8_t *out, size_t nout, > + Error **errp) > +{ > + static const int hash_map[QCRYPTO_HASH_ALG__MAX] = { > + [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5, > + [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1, > + [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256, > + }; > + int ret; > + > + if (hash >= G_N_ELEMENTS(hash_map) || > + hash_map[hash] == GCRY_MD_NONE) { > + error_setg(errp, "Unexpected hash algorithm %d", hash); > + return -1; > + } > + > + ret = gcry_kdf_derive(key, nkey, GCRY_KDF_PBKDF2, > + hash_map[hash], > + salt, nsalt, iterations, > + nout, out); > + if (ret != 0) { > + error_setg(errp, "Cannot derive password: %s", > + gcry_strerror(ret)); > + return -1; > + } > + > + return 0; > +} > diff --git a/crypto/pbkdf-nettle.c b/crypto/pbkdf-nettle.c > new file mode 100644 > index 0000000..1aa7395 > --- /dev/null > +++ b/crypto/pbkdf-nettle.c > @@ -0,0 +1,65 @@ > +/* > + * QEMU Crypto PBKDF support (Password-Based Key Derivation Function) > + * > + * Copyright (c) 2015-2016 Red Hat, Inc. > + * > + * This 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 of the License, or (at your option) any later version. > + * > + * This 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 this library; if not, see > <http://www.gnu.org/licenses/>. > + * > + */ > + > +#include "qemu/osdep.h" > +#include "crypto/pbkdf.h" > +#include "nettle/pbkdf2.h"
I get the following building error: CC crypto/pbkdf.o CC crypto/pbkdf-nettle.o CC crypto/ivgen.o crypto/pbkdf-nettle.c:23:27: error: nettle/pbkdf2.h: No such file or directory crypto/pbkdf-nettle.c: In function ‘qcrypto_pbkdf2’: crypto/pbkdf-nettle.c:46: warning: implicit declaration of function ‘pbkdf2_hmac_sha1’ crypto/pbkdf-nettle.c:46: warning: nested extern declaration of ‘pbkdf2_hmac_sha1’ crypto/pbkdf-nettle.c:53: warning: implicit declaration of function ‘pbkdf2_hmac_sha256’ crypto/pbkdf-nettle.c:53: warning: nested extern declaration of ‘pbkdf2_hmac_sha256’ make: *** [crypto/pbkdf-nettle.o] Error 1 make: *** Waiting for unfinished jobs.... rpm -qf /usr/include/nettle/ libnettle-devel-2.4-8.1.2 The nettle version is very old...... The OS is SUSE 11 SP3. Thanks Wen Congyang