All of lore.kernel.org
 help / color / mirror / Atom feed
* [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
@ 2010-07-28  8:33 Jussi.Laako
  2010-07-29 12:01 ` Milan Broz
  0 siblings, 1 reply; 5+ messages in thread
From: Jussi.Laako @ 2010-07-28  8:33 UTC (permalink / raw)
  To: agk, mbroz, dm-crypt; +Cc: Alexander.Valitov

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]

Hi,

In some embedded environments, like in some where MeeGo is used, it is
needed to reduce number of packages with duplicate functionality in order to
save flash space. Thus we have created a patch to add optional support for
OpenSSL's libcrypto as well as make libgcrypt optional, making it possible
to build cryptsetup in environments lacking either one. Or to support both,
if that makes any sense.

Preferably, the hash plugin interface should be extended and used also in
luks/ part, but we didn't start making such a drastic change.

The new OpenSSL plugin can be made cleaner once OpenSSL 1.x becomes more
common, but at the moment the 0.x series is still widely used and lacks some
of the APIs 1.x has.

Comments are more than welcome. :)


Best regards,

    - Jussi Laako


[-- Attachment #2: meego-cryptsetup.patch --]
[-- Type: application/octet-stream, Size: 22419 bytes --]

diff --git a/configure.in b/configure.in
index 936d165..3d45361 100644
--- a/configure.in
+++ b/configure.in
@@ -31,6 +31,8 @@ AC_HEADER_STDC
 AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
 	ctype.h unistd.h locale.h)
 
+PKG_PROG_PKG_CONFIG([0.22])
+
 AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR('You need the uuid library')])
 AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR('You need the device-mapper library')])
 
@@ -40,8 +42,6 @@ AC_SUBST(UUID_LIBS, $LIBS)
 LIBS=$saved_LIBS
 
 
-AM_PATH_LIBGCRYPT(1.1.42,,[AC_MSG_ERROR('You need the gcrypt library')])
-
 AC_CHECK_FUNCS([posix_memalign])
 
 AC_C_CONST
@@ -73,6 +73,51 @@ AC_ARG_ENABLE(shared-library,
 enable_shared_library=yes)
 AM_CONDITIONAL(STATIC_LIBRARY, test x$enable_shared_library = xno)
 
+AC_ARG_ENABLE(plugins,
+[  --enable-plugins        disable shared library plugins],,enable_plugins=no)
+if test "x$enable_plugins" = xyes; then
+	AC_DEFINE(USE_PLUGINS, 1, [Define if you wish to use the plugin loader])
+fi
+
+AC_ARG_ENABLE(, [
+Modules:
+  --with-MODULE[[=shared]]  builds the module MODULE as a shared library plugin
+],,)
+
+AC_ARG_ENABLE(all,
+[  --disable-all           disable all modules built by default],,enable_all=default)
+
+AC_ARG_ENABLE(gcrypt,
+[  --disable-gcrypt        disable gcrypt support [[default=no]]], ,
+	enable_gcrypt=yes)
+if test x$enable_gcrypt = xyes; then
+	AC_CHECK_LIB(gcrypt, gcry_check_version, have_gcrypt=yes, have_gcrypt=no)
+fi
+AM_CONDITIONAL(BUILD_LIBGCRYPT, test x$have_gcrypt = xyes)
+AM_CONDITIONAL(SHARED_LIBGCRYPT,
+	test x$enable_shared_library = xyes -a x$have_gcrypt = xyes)
+if test x$have_gcrypt = xyes; then
+	LIBGCRYPT_CFLAGS="`libgcrypt-config --cflags`"
+	LIBGCRYPT_LIBS="`libgcrypt-config --libs`"
+	AC_SUBST(LIBGCRYPT_CFLAGS)
+	AC_SUBST(LIBGCRYPT_LIBS)
+fi
+
+AC_ARG_ENABLE(openssl,
+[  --disable-openssl       disable openssl support [[default=no]]], ,
+	enable_openssl=yes)
+if test x$enable_openssl = xyes; then
+	PKG_CHECK_MODULES([OPENSSL], [libcrypto >= 0.9.8], AC_CHECK_LIB(crypto, SHA512, have_openssl=yes, have_openssl=no),
+							    have_openssl=no)
+fi
+AM_CONDITIONAL(BUILD_OPENSSL, test x$have_openssl = xyes)
+AM_CONDITIONAL(SHARED_OPENSSL,
+	test x$enable_shared_library = xyes -a x$have_openssl = xyes)
+
+if test x$have_gcrypt != xyes -a x$have_openssl != xyes; then
+	AC_MSG_ERROR('You need openSSL or/and gcrypt library as a crypto backend')
+fi
+
 AC_ARG_ENABLE(selinux,
 [  --disable-selinux       disable selinux support [[default=auto]]],[], [])
 
@@ -87,6 +132,7 @@ if AC_RUN_LOG([pkg-config --exists --print-errors devmapper]); then
 	fi
 	PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03])
 	LIBS="$LIBS $DEVMAPPER_LIBS"
+	AC_SUBST(LIBDEVMAPPER_CFLAGS)
 else
 	AC_CHECK_LIB(devmapper, dm_task_set_name,,
 		[AC_MSG_ERROR('You need the device-mapper library')])
@@ -95,6 +141,9 @@ else
 	DEVMAPPER_LIBS=$LIBS
 fi
 
+AM_CONDITIONAL(BUILD_LIBDEVMAPPER, test x$build_static = xyes)
+AM_CONDITIONAL(SHARED_LIBDEVMAPPER, test x$build_shared = xyes)
+
 AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
 if test "x$enable_udev" = xyes; then
 	if test "x$have_cookie" = xno; then
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6068751..11b915f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,6 +3,30 @@ moduledir = $(libdir)/cryptsetup
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libcryptsetup.pc
 
+if BUILD_LIBGCRYPT
+_LIBGCRYPT_LIBADD = @LIBGCRYPT_LIBS@
+_LIBGCRYPT_SOURCES = gcrypt.c
+_LIBGCRYPT_CFLAGS = -DBUILTIN_GCRYPT
+endif
+libcrypto_gcrypt_la_SOURCES = gcrypt.c
+libcrypto_gcrypt_la_LDFLAGS = -avoid-version -module
+libcrypto_gcrypt_la_LIBADD = @LIBGCRYPT_LIBS@
+if SHARED_LIBGCRYPT
+_LIBGCRYPT_SHLIB = libcrypto_gcrypt.la
+endif
+
+if BUILD_OPENSSL
+_OPENSSL_LIBADD = @OPENSSL_LIBS@
+_OPENSSL_SOURCES = openssl.c
+_OPENSSL_CFLAGS = -DBUILTIN_OPENSSL
+endif
+libcrypto_openssl_la_SOURCES = openssl.c
+libcrypto_openssl_la_LDFLAGS = -avoid-version -module
+libcrypto_openssl_la_LIBADD = @OPENSSL_LIBS@
+if SHARED_OPENSSL
+_OPENSSL_SHLIB = libcrypto_openssl.la
+endif
+
 INCLUDES = \
 	-I$(top_srcdir)				\
 	-I$(top_srcdir)/luks			\
@@ -13,10 +37,21 @@ INCLUDES = \
 	-DVERSION=\""$(VERSION)"\"		\
 	-D_GNU_SOURCE				\
 	-D_LARGEFILE64_SOURCE			\
-	-D_FILE_OFFSET_BITS=64
+	-D_FILE_OFFSET_BITS=64			\
+	@LIBDEVMAPPER_CFLAGS@			\
+	$(_LIBDEVMAPPER_CFLAGS)			\
+	@LIBGCRYPT_CFLAGS@			\
+	$(_LIBGCRYPT_CFLAGS)			\
+	@OPENSSL_CFLAGS@			\
+	$(_OPENSSL_CFLAGS)
 
 lib_LTLIBRARIES = libcryptsetup.la
 
+module_LTLIBRARIES = \
+	$(_LIBDEVMAPPER_SHLIB)			\
+	$(_LIBGCRYPT_SHLIB)			\
+	$(_OPENSSL_SHLIB)
+
 if STATIC_LIBRARY
 _STATIC_LIBRARY = -static
 endif
@@ -28,9 +63,12 @@ libcryptsetup_la_LDFLAGS = \
 	-Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
 	-version-info @LIBCRYPTSETUP_VERSION_INFO@
 
-libcryptsetup_la_CFLAGS = -Wall @LIBGCRYPT_CFLAGS@
+libcryptsetup_la_CFLAGS = -Wall
 
 libcryptsetup_la_LIBADD = \
+	$(_LIBDEVMAPPER_LIBADD)			\
+	$(_LIBGCRYPT_LIBADD)			\
+	$(_OPENSSL_LIBADD)			\
 	@UUID_LIBS@				\
 	@DEVMAPPER_LIBS@			\
 	@LIBGCRYPT_LIBS@			\
@@ -46,7 +84,9 @@ libcryptsetup_la_SOURCES = \
 	utils_debug.c				\
 	backends.c				\
 	libdevmapper.c				\
-	gcrypt.c
+	$(_LIBDEVMAPPER_SOURCES)		\
+	$(_LIBGCRYPT_SOURCES)			\
+	$(_OPENSSL_SOURCES)
 
 include_HEADERS = libcryptsetup.h
 
diff --git a/lib/backends.c b/lib/backends.c
index e2c441d..27e20a1 100644
--- a/lib/backends.c
+++ b/lib/backends.c
@@ -7,9 +7,31 @@
 #include "internal.h"
 
 extern struct hash_backend hash_gcrypt_backend;
+extern struct hash_backend hash_openssl_backend;
+extern struct setup_backend setup_libdevmapper_backend;
+
+#ifdef USE_PLUGINS
+static void init_plugins(void)
+{
+}
+#else /* USE_PLUGINS */
+#	define init_plugins()	do { } while(0)
+#endif /* USE_PLUGINS */
 
 static struct hash_backend *hash_backends[] = {
+#ifdef BUILTIN_GCRYPT
 	&hash_gcrypt_backend,
+#endif
+#ifdef BUILTIN_OPENSSL
+	&hash_openssl_backend,
+#endif
+	NULL
+};
+
+static struct setup_backend *setup_backends[] = {
+#ifdef BUILTIN_LIBDEVMAPPER
+	&setup_libdevmapper_backend,
+#endif
 	NULL
 };
 
@@ -17,6 +39,8 @@ struct hash_backend *get_hash_backend(const char *name)
 {
 	struct hash_backend **backend;
 
+	init_plugins();
+
 	for(backend = hash_backends; *backend; backend++)
 		if (!name || strcmp(name, (*backend)->name) == 0)
 			break;
@@ -94,3 +118,22 @@ out:
 
 	return r;
 }
+
+struct setup_backend *get_setup_backend(const char *name)
+{
+	struct setup_backend **backend;
+
+	init_plugins();
+
+	for(backend = setup_backends; *backend; backend++)
+		if (!name || strcmp(name, (*backend)->name) == 0)
+			break;
+
+	return *backend;
+}
+
+void put_setup_backend(struct setup_backend *backend)
+{
+#ifdef USE_PLUGINS
+#endif
+}
diff --git a/lib/gcrypt.c b/lib/gcrypt.c
index cfbcdc7..e68fd8b 100644
--- a/lib/gcrypt.c
+++ b/lib/gcrypt.c
@@ -10,7 +10,7 @@
 #define MAX_DIGESTS		64
 #define GCRYPT_REQ_VERSION	"1.1.42"
 
-int init_crypto(void)
+int init_gcrypt(void)
 {
 	if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
 		if (!gcry_check_version (GCRYPT_REQ_VERSION))
diff --git a/lib/internal.h b/lib/internal.h
index 7b31cf8..6d741a7 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -40,6 +40,19 @@ struct hash_backend {
 	void			(*free_hashes)(struct hash_type *hashes);
 };
 
+struct setup_backend {
+	const char	*name;
+	int		(*init)(void);
+	void		(*exit)(void);
+	int		(*create)(int reload, struct crypt_options *options,
+			          const char *key, const char *uuid);
+	int		(*status)(int details, struct crypt_options *options,
+			          char **key);
+	int		(*remove)(int force, struct crypt_options *options);
+
+	const char *	(*dir)(void);
+};
+
 struct device_infos {
 	uint64_t	size;
 	int		readonly;
diff --git a/lib/openssl.c b/lib/openssl.c
new file mode 100644
index 0000000..fe2374c
--- /dev/null
+++ b/lib/openssl.c
@@ -0,0 +1,306 @@
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/ripemd.h>
+
+#include "libcryptsetup.h"
+#include "internal.h"
+
+#define NUM_DIGESTS		5
+
+typedef enum _e_digests
+{
+	DIGEST_MD5 = 0,
+	DIGEST_SHA1,
+	DIGEST_SHA256,
+	DIGEST_SHA512,
+	DIGEST_RIPEMD160
+} digests_t;
+
+static const char *digest_names[] = {
+	"md5",
+	"sha1",
+	"sha256",
+	"sha512",
+	"ripemd160"
+};
+
+
+int init_openssl(void)
+{
+	static int inited = 0;
+	if (!inited) {
+		inited = 1;
+		OpenSSL_add_all_digests();
+	} 
+	return 0;
+}
+
+static int openssl_hash_md5 (void *data, int size, char *key,
+                       int sizep, const char *passphrase)
+{
+	int len = MD5_DIGEST_LENGTH;
+	int round, i;
+	unsigned char md[MD5_DIGEST_LENGTH];
+	MD5_CTX ctx;
+
+	if (!MD5_Init(&ctx))
+		return -1;
+
+	for(round = 0; size; round++) {
+		/* hack from hashalot to avoid null bytes in key */
+		for(i = 0; i < round; i++)
+			if (!MD5_Update(&ctx, "A", 1))
+				return -1;
+
+		if (!MD5_Update(&ctx, passphrase, sizep))
+			return -1;
+
+		if (!MD5_Final(md, &ctx))
+			return -1;
+		if (len > size)
+			len = size;
+		memcpy(key, md, len);
+
+		key += len;
+		size -= len;
+		/* not needed, *_Final() resets the hash */
+		/*if (size)
+			if (!MD5_Init(&ctx))
+				return -1;*/
+	}
+	memset(md, 0x00, MD5_DIGEST_LENGTH);
+
+	return 0;
+}
+
+static int openssl_hash_sha1 (void *data, int size, char *key,
+                       int sizep, const char *passphrase)
+{
+	int len = SHA_DIGEST_LENGTH;
+	int round, i;
+	unsigned char md[SHA_DIGEST_LENGTH];
+	SHA_CTX ctx;
+
+	if (!SHA_Init(&ctx))
+		return -1;
+
+	for(round = 0; size; round++) {
+		/* hack from hashalot to avoid null bytes in key */
+		for(i = 0; i < round; i++)
+			if (!SHA_Update(&ctx, "A", 1))
+				return -1;
+
+		if (!SHA_Update(&ctx, passphrase, sizep))
+			return -1;
+
+		if (!SHA_Final(md, &ctx))
+			return -1;
+		if (len > size)
+			len = size;
+		memcpy(key, md, len);
+
+		key += len;
+		size -= len;
+		/* not needed, *_Final() resets the hash */
+		/*if (size)
+			if (!SHA_Init(&ctx))
+				return -1;*/
+	}
+	memset(md, 0x00, SHA_DIGEST_LENGTH);
+
+	return 0;
+}
+
+static int openssl_hash_sha256 (void *data, int size, char *key,
+                       int sizep, const char *passphrase)
+{
+	int len = SHA256_DIGEST_LENGTH;
+	int round, i;
+	unsigned char md[SHA256_DIGEST_LENGTH];
+	SHA256_CTX ctx;
+
+	if (!SHA256_Init(&ctx))
+		return -1;
+
+	for(round = 0; size; round++) {
+		/* hack from hashalot to avoid null bytes in key */
+		for(i = 0; i < round; i++)
+			if (!SHA256_Update(&ctx, "A", 1))
+				return -1;
+
+		if (!SHA256_Update(&ctx, passphrase, sizep))
+			return -1;
+
+		if (!SHA256_Final(md, &ctx))
+			return -1;
+		if (len > size)
+			len = size;
+		memcpy(key, md, len);
+
+		key += len;
+		size -= len;
+		/* not needed, *_Final() resets the hash */
+		/*if (size)
+			if (!SHA256_Init(&ctx))
+				return -1;*/
+	}
+	memset(md, 0x00, SHA256_DIGEST_LENGTH);
+
+	return 0;
+}
+
+static int openssl_hash_sha512 (void *data, int size, char *key,
+                       int sizep, const char *passphrase)
+{
+	int len = SHA512_DIGEST_LENGTH;
+	int round, i;
+	unsigned char md[SHA512_DIGEST_LENGTH];
+	SHA512_CTX ctx;
+
+	if (!SHA512_Init(&ctx))
+		return -1;
+
+	for(round = 0; size; round++) {
+		/* hack from hashalot to avoid null bytes in key */
+		for(i = 0; i < round; i++)
+			if (!SHA512_Update(&ctx, "A", 1))
+				return -1;
+
+		if (!SHA512_Update(&ctx, passphrase, sizep))
+			return -1;
+
+		if (!SHA512_Final(md, &ctx))
+			return -1;
+		if (len > size)
+			len = size;
+		memcpy(key, md, len);
+
+		key += len;
+		size -= len;
+		/* not needed, *_Final() resets the hash */
+		/*if (size)
+			if (!SHA512_Init(&ctx))
+				return -1;*/
+	}
+	memset(md, 0x00, SHA512_DIGEST_LENGTH);
+
+	return 0;
+}
+
+static int openssl_hash_ripemd160 (void *data, int size, char *key,
+                       int sizep, const char *passphrase)
+{
+	int len = RIPEMD160_DIGEST_LENGTH;
+	int round, i;
+	unsigned char md[RIPEMD160_DIGEST_LENGTH];
+	RIPEMD160_CTX ctx;
+
+	if (!RIPEMD160_Init(&ctx))
+		return -1;
+
+	for(round = 0; size; round++) {
+		/* hack from hashalot to avoid null bytes in key */
+		for(i = 0; i < round; i++)
+			if (!RIPEMD160_Update(&ctx, "A", 1))
+				return -1;
+
+		if (!RIPEMD160_Update(&ctx, passphrase, sizep))
+			return -1;
+
+		if (!RIPEMD160_Final(md, &ctx))
+			return -1;
+		if (len > size)
+			len = size;
+		memcpy(key, md, len);
+
+		key += len;
+		size -= len;
+		/* not needed, *_Final() resets the hash */
+		/*if (size)
+			if (!RIPEMD160_Init(&ctx))
+				return -1;*/
+	}
+	memset(md, 0x00, RIPEMD160_DIGEST_LENGTH);
+
+	return 0;
+}
+
+static struct hash_type *openssl_get_hashes(void)
+{
+	struct hash_type *hashes;
+	int size = NUM_DIGESTS;
+	int i;
+
+	hashes = malloc(sizeof(*hashes) * (size + 1));
+	if (!hashes)
+		return NULL;
+
+	for(i = 0; i < size; i++) {
+		hashes[i].name = NULL;
+		hashes[i].private = NULL;
+	}
+
+	for(i = 0; i < size; i++) {
+		hashes[i].name = strdup(digest_names[i]);
+		if(!hashes[i].name)
+			goto err;
+		/*hashes[i].private = ;
+		if(!hashes[i].private)
+			goto err;*/
+		switch (i)
+		{
+			case DIGEST_MD5:
+				hashes[i].fn = openssl_hash_md5;
+				break;
+			case DIGEST_SHA1:
+				hashes[i].fn = openssl_hash_sha1;
+				break;
+			case DIGEST_SHA256:
+				hashes[i].fn = openssl_hash_sha256;
+				break;
+			case DIGEST_SHA512:
+				hashes[i].fn = openssl_hash_sha512;
+				break;
+			case DIGEST_RIPEMD160:
+				hashes[i].fn = openssl_hash_ripemd160;
+				break;
+			default:
+				goto err;
+		}
+	}
+	hashes[i].name = NULL;
+	hashes[i].private = NULL;
+	hashes[i].fn = NULL;
+
+	return hashes;
+
+err:
+	for(i = 0; i < size; i++) {
+		if (hashes[i].name) free(hashes[i].name);
+		if (hashes[i].private) free(hashes[i].private);
+	}
+	free(hashes);
+
+	return NULL;
+}
+
+static void openssl_free_hashes(struct hash_type *hashes)
+{
+	struct hash_type *hash;
+
+	for(hash = hashes; hash->name; hash++) {
+		if (hash->name) free(hash->name);
+		if (hash->private) free(hash->private);
+	}
+	free(hashes);
+}
+
+struct hash_backend hash_openssl_backend = {
+	.name = "openssl",
+	.get_hashes = openssl_get_hashes,
+	.free_hashes = openssl_free_hashes
+};
diff --git a/lib/setup.c b/lib/setup.c
index 720ea9b..0fcf912 100644
--- a/lib/setup.c
+++ b/lib/setup.c
@@ -38,6 +38,27 @@ struct crypt_device {
 	void *password_usrptr;
 };
 
+#ifdef BUILTIN_OPENSSL
+int init_openssl(void);
+#endif
+#ifdef BUILTIN_GCRYPT
+int init_gcrypt(void);
+#endif
+
+int init_crypto(void)
+{
+	int i = 0;
+#ifdef BUILTIN_OPENSSL
+	if ((i = init_openssl()) != 0)
+		return i;
+#endif
+#ifdef BUILTIN_GCRYPT
+	if ((i = init_gcrypt()) != 0)
+		return i;
+#endif
+	return i;
+}
+
 /* Log helper */
 static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
 static int _debug_level = 0;
diff --git a/luks/Makefile.am b/luks/Makefile.am
index 7ce43ca..6c96083 100644
--- a/luks/Makefile.am
+++ b/luks/Makefile.am
@@ -2,7 +2,16 @@ moduledir = $(libdir)/cryptsetup
 
 noinst_LTLIBRARIES = libluks.la
 
-libluks_la_CFLAGS = -Wall @LIBGCRYPT_CFLAGS@
+libluks_la_CFLAGS = -Wall
+
+if BUILD_LIBGCRYPT
+libluks_la_CFLAGS += @LIBGCRYPT_CFLAGS@
+_LIBGCRYPT_CFLAGS = -DBUILTIN_GCRYPT
+endif
+
+if BUILD_OPENSSL
+_OPENSSL_CFLAGS = -DBUILTIN_OPENSSL
+endif
 
 libluks_la_SOURCES = \
 	af.c \
@@ -19,5 +28,7 @@ libluks_la_SOURCES = \
 INCLUDES = -D_GNU_SOURCE			\
 	-D_LARGEFILE64_SOURCE                   \
 	-D_FILE_OFFSET_BITS=64                  \
+	$(_OPENSSL_CFLAGS)			\
+	$(_LIBGCRYPT_CFLAGS)			\
         -I$(top_srcdir)/lib
 
diff --git a/luks/af.c b/luks/af.c
index a11ceac..064de56 100644
--- a/luks/af.c
+++ b/luks/af.c
@@ -25,7 +25,15 @@
 #include <string.h>
 #include <netinet/in.h>
 #include <errno.h>
+
+#if defined(BUILTIN_OPENSSL) /* try to use OpenSSL first*/
+#include <openssl/evp.h>
+#elif defined(BUILTIN_GCRYPT)
 #include <gcrypt.h>
+#else
+#error "Neither BUILTIN_GCRYPT nor BUILTIN_OPENSSL are defined"
+#endif
+
 #include "random.h"
 
 static void XORblock(char const *src1, char const *src2, char *dst, size_t n)
@@ -36,6 +44,24 @@ static void XORblock(char const *src1, char const *src2, char *dst, size_t n)
 		dst[j] = src1[j] ^ src2[j];
 }
 
+#ifdef BUILTIN_OPENSSL
+static int hash_buf(char *src, char *dst, uint32_t iv, int len, const EVP_MD *hash_id)
+{
+	EVP_MD_CTX mdctx;
+	unsigned char digest[EVP_MAX_MD_SIZE];
+
+	iv = htonl(iv);
+
+	if (EVP_DigestInit(&mdctx, hash_id) != 1)
+		return 1;
+	EVP_DigestUpdate(&mdctx, (unsigned char *)&iv, sizeof(iv));
+	EVP_DigestUpdate(&mdctx, src, len);
+	EVP_DigestFinal_ex(&mdctx, digest, NULL);
+	memcpy(dst, digest, len);
+	EVP_MD_CTX_cleanup(&mdctx);
+	return 0;
+}
+#else
 static int hash_buf(char *src, char *dst, uint32_t iv, int len, int hash_id)
 {
 	gcry_md_hd_t hd;
@@ -51,14 +77,23 @@ static int hash_buf(char *src, char *dst, uint32_t iv, int len, int hash_id)
 	gcry_md_close(hd);
 	return 0;
 }
+#endif
 
 /* diffuse: Information spreading over the whole dataset with
  * the help of hash function.
  */
 
+#ifdef BUILTIN_OPENSSL
+static int diffuse(char *src, char *dst, size_t size, const EVP_MD *hash_id)
+#else
 static int diffuse(char *src, char *dst, size_t size, int hash_id)
+#endif
 {
+#ifdef BUILTIN_OPENSSL
+	unsigned int digest_size = EVP_MD_size(hash_id);
+#else
 	unsigned int digest_size = gcry_md_get_algo_dlen(hash_id);
+#endif
 	unsigned int i, blocks, padding;
 
 	blocks = size / digest_size;
@@ -90,10 +125,16 @@ int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers,
 	unsigned int i;
 	char *bufblock;
 	int r = -EINVAL;
+#ifdef BUILTIN_OPENSSL
+        const EVP_MD *hash_id;
+        if(!(hash_id = EVP_get_digestbyname(hash)))
+		return -EINVAL;
+#else
 	int hash_id;
 
 	if (!(hash_id = gcry_md_map_name(hash)))
 		return -EINVAL;
+#endif
 
 	if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM;
 
@@ -119,11 +160,16 @@ int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers,
 	unsigned int i;
 	char *bufblock;
 	int r = -EINVAL;
+#ifdef BUILTIN_OPENSSL
+        const EVP_MD *hash_id;
+        if(!(hash_id = EVP_get_digestbyname(hash)))
+		return -EINVAL;
+#else
 	int hash_id;
 
 	if (!(hash_id = gcry_md_map_name(hash)))
 		return -EINVAL;
-
+#endif
 	if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM;
 
 	memset(bufblock,0,blocksize);
diff --git a/luks/pbkdf.c b/luks/pbkdf.c
index fa1f720..0ad04a0 100644
--- a/luks/pbkdf.c
+++ b/luks/pbkdf.c
@@ -27,13 +27,20 @@
 #include <signal.h>
 #include <alloca.h>
 #include <sys/time.h>
+#include <string.h>
+#if defined(BUILTIN_OPENSSL) /* try to use OpenSSL first*/
+#include <openssl/hmac.h>
+#elif defined(BUILTIN_GCRYPT)
 #include <gcrypt.h>
+#else
+#error "Neither BUILTIN_GCRYPT nor BUILTIN_OPENSSL are defined"
+#endif
+
+int init_crypto(void);
 
 static volatile uint64_t __PBKDF2_global_j = 0;
 static volatile uint64_t __PBKDF2_performance = 0;
 
-int init_crypto(void);
-
 /*
  * 5.2 PBKDF2
  *
@@ -68,12 +75,19 @@ static int pkcs5_pbkdf2(const char *hash,
 			unsigned int c, unsigned int dkLen,
 			char *DK, int perfcheck)
 {
+#ifdef BUILTIN_OPENSSL
+	HMAC_CTX prf;
+	const EVP_MD *PRF;
+	unsigned char p[EVP_MAX_MD_SIZE];
+#else
 	gcry_md_hd_t prf;
+        int PRF;
+	unsigned char *p;
+#endif
 	char U[MAX_PRF_BLOCK_LEN];
 	char T[MAX_PRF_BLOCK_LEN];
-	int PRF, i, k, rc = -EINVAL;
+	int i, k, rc = -EINVAL;
 	unsigned int u, hLen, l, r;
-	unsigned char *p;
 	size_t tmplen = Slen + 4;
 	char *tmp;
 
@@ -84,11 +98,18 @@ static int pkcs5_pbkdf2(const char *hash,
 	if (init_crypto())
 		return -ENOSYS;
 
+#ifdef BUILTIN_OPENSSL
+        if(!(PRF = EVP_get_digestbyname(hash)))
+		return -EINVAL;
+
+        hLen = EVP_MD_size(PRF);
+#else
 	PRF = gcry_md_map_name(hash);
 	if (PRF == 0)
 		return -EINVAL;
 
 	hLen = gcry_md_get_algo_dlen(PRF);
+#endif
 	if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
 		return -EINVAL;
 
@@ -168,16 +189,40 @@ static int pkcs5_pbkdf2(const char *hash,
 	 *
 	 */
 
+#ifdef BUILTIN_OPENSSL
+        HMAC_CTX_init(&prf);
+#else
 	if(gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC))
 		return -EINVAL;
 
 	if (gcry_md_setkey(prf, P, Plen))
 		goto out;
+#endif
 
 	for (i = 1; (uint) i <= l; i++) {
 		memset(T, 0, hLen);
 
 		for (u = 1; u <= c ; u++) {
+#ifdef BUILTIN_OPENSSL
+			/*if((HMAC_Init_ex(&prf, P, Plen, PRF, NULL)) != 1)
+				goto out;*/
+			/* don't return values in versions of OpenSSL before 1.0.0 */
+			HMAC_Init_ex(&prf, P, Plen, PRF, NULL);
+
+			if (u == 1) {
+				memcpy(tmp, S, Slen);
+				tmp[Slen + 0] = (i & 0xff000000) >> 24;
+				tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
+				tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
+				tmp[Slen + 3] = (i & 0x000000ff) >> 0;
+
+				HMAC_Update(&prf, (unsigned char *)tmp, tmplen);
+			} else {
+				HMAC_Update(&prf, (unsigned char *)U, hLen);
+			}
+
+			HMAC_Final(&prf, p, NULL);
+#else
 			gcry_md_reset(prf);
 
 			if (u == 1) {
@@ -193,6 +238,7 @@ static int pkcs5_pbkdf2(const char *hash,
 			}
 
 			p = gcry_md_read(prf, PRF);
+#endif
 			if (p == NULL)
 				goto out;
 
@@ -214,7 +260,11 @@ static int pkcs5_pbkdf2(const char *hash,
 	}
 	rc = 0;
 out:
+#ifdef BUILTIN_OPENSSL
+        HMAC_CTX_cleanup(&prf);
+#else
 	gcry_md_close(prf);
+#endif
 	return rc;
 }
 
@@ -229,6 +279,15 @@ int PBKDF2_HMAC(const char *hash,
 
 int PBKDF2_HMAC_ready(const char *hash)
 {
+#ifdef BUILTIN_OPENSSL
+        const EVP_MD *hash_id;
+
+        if(!(hash_id = EVP_get_digestbyname(hash)))
+		return -EINVAL;
+
+        if (EVP_MD_size(hash_id) < 20)
+		return -EINVAL;
+#else
 	int hash_id = gcry_md_map_name(hash);
 
 	if (!hash_id)
@@ -237,6 +296,7 @@ int PBKDF2_HMAC_ready(const char *hash)
 	/* Used hash must have at least 160 bits */
 	if (gcry_md_get_algo_dlen(hash_id) < 20)
 		return -EINVAL;
+#endif
 
 	return 1;
 }
diff --git a/tests/align-test b/tests/align-test
index 2fdb9b6..780d8f8 100755
--- a/tests/align-test
+++ b/tests/align-test
@@ -98,5 +98,6 @@ dmsetup create luks0xbabe --table "0 32768 linear $DEV2 0"
 format 256 2112
 format 128 1088
 format 128 8192 8192
+sync
 dmsetup remove luks0xbabe
 cleanup
diff --git a/tests/compat-test b/tests/compat-test
index b7f6589..b4c8fac 100755
--- a/tests/compat-test
+++ b/tests/compat-test
@@ -41,6 +41,7 @@ function prepare()
 		exit 0
 	fi
 
+	sync
 	[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
 
 	if [ ! -e $KEY1 ]; then

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-07-30 14:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-28  8:33 [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional Jussi.Laako
2010-07-29 12:01 ` Milan Broz
2010-07-29 12:27   ` Arno Wagner
2010-07-30 11:46   ` Valitov Alexander
2010-07-30 14:21   ` Jussi.Laako

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.