* [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* Re: [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
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
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Milan Broz @ 2010-07-29 12:01 UTC (permalink / raw)
To: Jussi.Laako; +Cc: dm-crypt, Alexander.Valitov, agk
On 07/28/2010 10:33 AM, Jussi.Laako@nokia.com wrote:
> 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.
Hi,
I intentionally removed plugin interface and [lib]cryptsetup now depends
on libgcrypt.
Well, since that decision I found some problems in gcrypt (which upstream
refused to fix) so seems there is now yet another reason to support more
crypto backends. (It should support gcrypt, nss, openssl at least).
But I do not want to use runtime plugin architecture but compile time
decision only.
So for you patch:
- seems you are reverting some configure options which are not needed,
I think it is enough to have someting like --with-crypto=[gcrypt,openssl,nss]
or so.
- setup_backend is not needed, it will always depend on device-mapper
(did I miss anything? it is not used even in your patch...just defined there)
- using #ifdef is not ideal, mainly in crypto code - it is easy to break
algorithm when using wrong defines. It need properly define crypto backend
callbacks and switch only its implementations. And include tests
(I have already PBKDF2 testvectors test, that should be used for all backends.)
- I think openssl backend function should not duplicate all the code
for every algorithm
- you added some "sync" calls to test - is it another problem?
(should not be needed at all)
- there is still hardcoded gcrypt logic on some places (including api-test),
so it still links to gcrypt, all regression tests must run with all supported
backends. Probably some basic list of must-have algorithms should be defined
for crypto backends. (e.g. I am using whirlpool hash for testing, not all crypto
backend support it currently.)
So, in general, I agree we should support more crypto backends.
Are you ok with supporting this in compile time only (so there is always
only one backend in compiled binaries - depends on distro preference)?
If so, I'll add this to my TODO list for next versions.
Thanks,
Milan
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
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
2 siblings, 0 replies; 5+ messages in thread
From: Arno Wagner @ 2010-07-29 12:27 UTC (permalink / raw)
To: dm-crypt
On Thu, Jul 29, 2010 at 02:01:52PM +0200, Milan Broz wrote:
> On 07/28/2010 10:33 AM, Jussi.Laako@nokia.com wrote:
> > 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.
>
> Hi,
>
> I intentionally removed plugin interface and [lib]cryptsetup now depends
> on libgcrypt.
>
> Well, since that decision I found some problems in gcrypt (which upstream
> refused to fix) so seems there is now yet another reason to support more
> crypto backends. (It should support gcrypt, nss, openssl at least).
Well, noting is ever perfect, so avoiding strong dependencies is
definitely a good idea.
> But I do not want to use runtime plugin architecture but compile time
> decision only.
I like that for security resons, due to increased clarity
about what is used and lower complexity.
> So for you patch:
> - seems you are reverting some configure options which are not needed,
> I think it is enough to have someting like --with-crypto=[gcrypt,openssl,nss]
> or so.
I agree.
> - setup_backend is not needed, it will always depend on device-mapper
> (did I miss anything? it is not used even in your patch...just defined there)
>
> - using #ifdef is not ideal, mainly in crypto code - it is easy to break
> algorithm when using wrong defines. It need properly define crypto backend
> callbacks and switch only its implementations. And include tests
> (I have already PBKDF2 testvectors test, that should be used for all
> backends.)
Uniform tests are definitely a very good idea.
> - I think openssl backend function should not duplicate all the code
> for every algorithm
>
> - you added some "sync" calls to test - is it another problem?
> (should not be needed at all)
>
> - there is still hardcoded gcrypt logic on some places (including api-test),
> so it still links to gcrypt, all regression tests must run with all supported
> backends. Probably some basic list of must-have algorithms should be defined
> for crypto backends. (e.g. I am using whirlpool hash for testing, not all crypto
> backend support it currently.)
I agree. Which algorithms are supported by all backend and
which require a specific backend will also become a FAQ item ;-)
We could run a poll here for a month or so about what people
consider must-have.
>
> So, in general, I agree we should support more crypto backends.
>
> Are you ok with supporting this in compile time only (so there is always
> only one backend in compiled binaries - depends on distro preference)?
>
> If so, I'll add this to my TODO list for next versions.
I would support that. Seems like a good idea.
Arno
--
Arno Wagner, Dr. sc. techn., Dipl. Inform., CISSP -- Email: arno@wagner.name
GnuPG: ID: 1E25338F FP: 0C30 5782 9D93 F785 E79C 0296 797F 6B50 1E25 338F
----
Cuddly UI's are the manifestation of wishful thinking. -- Dylan Evans
If it's in the news, don't worry about it. The very definition of
"news" is "something that hardly ever happens." -- Bruce Schneier
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
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
2 siblings, 0 replies; 5+ messages in thread
From: Valitov Alexander @ 2010-07-30 11:46 UTC (permalink / raw)
To: Milan Broz, Jussi.Laako@nokia.com; +Cc: dm-crypt@saout.de, agk@redhat.com
Hi,
> - you added some "sync" calls to test - is it another problem?
> (should not be needed at all)
I added 'sync' because otherwise sometimes in tests this command:
# dmsetup remove volumeName
failed to remove volume and I got this error:
device-mapper: remove ioctl failed: Device or resource busy
Initially I added 'sleep 1' before 'dmsetup', but then decided to replace it with 'sync'.
'sync' also did the trick. So I kept it.
I didn't try to figure out what's the problem with 'dmsetup remove'
Best Regards,
Alexander Valitov
________________________________________
From: Milan Broz [mbroz@redhat.com]
Sent: 29 July 2010 15:01
To: Jussi.Laako@nokia.com
Cc: agk@redhat.com; dm-crypt@saout.de; Valitov Alexander
Subject: Re: [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
On 07/28/2010 10:33 AM, Jussi.Laako@nokia.com wrote:
> 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.
Hi,
I intentionally removed plugin interface and [lib]cryptsetup now depends
on libgcrypt.
Well, since that decision I found some problems in gcrypt (which upstream
refused to fix) so seems there is now yet another reason to support more
crypto backends. (It should support gcrypt, nss, openssl at least).
But I do not want to use runtime plugin architecture but compile time
decision only.
So for you patch:
- seems you are reverting some configure options which are not needed,
I think it is enough to have someting like --with-crypto=[gcrypt,openssl,nss]
or so.
- setup_backend is not needed, it will always depend on device-mapper
(did I miss anything? it is not used even in your patch...just defined there)
- using #ifdef is not ideal, mainly in crypto code - it is easy to break
algorithm when using wrong defines. It need properly define crypto backend
callbacks and switch only its implementations. And include tests
(I have already PBKDF2 testvectors test, that should be used for all backends.)
- I think openssl backend function should not duplicate all the code
for every algorithm
- you added some "sync" calls to test - is it another problem?
(should not be needed at all)
- there is still hardcoded gcrypt logic on some places (including api-test),
so it still links to gcrypt, all regression tests must run with all supported
backends. Probably some basic list of must-have algorithms should be defined
for crypto backends. (e.g. I am using whirlpool hash for testing, not all crypto
backend support it currently.)
So, in general, I agree we should support more crypto backends.
Are you ok with supporting this in compile time only (so there is always
only one backend in compiled binaries - depends on distro preference)?
If so, I'll add this to my TODO list for next versions.
Thanks,
Milan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [dm-crypt] [PATCH] support OpenSSL's libcrypto and make libgcrypt optional
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
2 siblings, 0 replies; 5+ messages in thread
From: Jussi.Laako @ 2010-07-30 14:21 UTC (permalink / raw)
To: mbroz; +Cc: dm-crypt, Alexander.Valitov, agk
[-- Attachment #1: Type: text/plain, Size: 2336 bytes --]
Hi,
On 29.7.2010 15:01, "ext Milan Broz" <mbroz@redhat.com> wrote:
> But I do not want to use runtime plugin architecture but compile time
> decision only.
Sounds reasonable.
> So for you patch:
> - seems you are reverting some configure options which are not needed,
> I think it is enough to have someting like --with-crypto=[gcrypt,openssl,nss]
> or so.
I can try to look into this later, though I'm not an autotool wizard... :)
> - using #ifdef is not ideal, mainly in crypto code - it is easy to break
> algorithm when using wrong defines. It need properly define crypto backend
> callbacks and switch only its implementations. And include tests
> (I have already PBKDF2 testvectors test, that should be used for all
> backends.)
Sounds good, I can update the OpenSSL specific code once the needed backend
changes are there.
> - I think openssl backend function should not duplicate all the code
> for every algorithm
True, there's no really nice way to have it with this backend interface
using the low-level OpenSSL crypto API. I rewrote the backend (attached) to
use a bit higher level EVP interface which made it a lot cleaner. The
initialization part is needed when the EVP_get_digestbyname() is in use.
When not using the name lookups but the code below, it shouldn't need
separate initialization.
Also needed once extra change to backends.c in order to call the
initialization. (incremental patch attached)
> - there is still hardcoded gcrypt logic on some places (including api-test),
> so it still links to gcrypt, all regression tests must run with all supported
> backends. Probably some basic list of must-have algorithms should be defined
> for crypto backends. (e.g. I am using whirlpool hash for testing, not all
> crypto backend support it currently.)
I'll look into this in September, unless Alexander has time to take a look
at that part earlier.
Quite common older versions of OpenSSL don't have whirlpool, but 1.x series
has it.
> Are you ok with supporting this in compile time only (so there is always
> only one backend in compiled binaries - depends on distro preference)?
Yes, that's OK, since we just like to avoid forcefully bringing in duplicate
functionality through dependencies, when possible.
Best regards,
- Jussi
[-- Attachment #2: meego-cryptsetup-backends.patch --]
[-- Type: application/octet-stream, Size: 590 bytes --]
diff --git a/lib/backends.c b/lib/backends.c
index 27e20a1..c451ac3 100644
--- a/lib/backends.c
+++ b/lib/backends.c
@@ -10,13 +10,12 @@ 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)
{
+#ifdef BUILTIN_OPENSSL
+ init_openssl();
+#endif /* BUILTIN_OPENSSL */
}
-#else /* USE_PLUGINS */
-# define init_plugins() do { } while(0)
-#endif /* USE_PLUGINS */
static struct hash_backend *hash_backends[] = {
#ifdef BUILTIN_GCRYPT
[-- Attachment #3: openssl.c --]
[-- Type: application/octet-stream, Size: 2888 bytes --]
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <openssl/evp.h>
#include "libcryptsetup.h"
#include "internal.h"
typedef enum _e_digests
{
DIGEST_MD5 = 0,
DIGEST_SHA1,
DIGEST_SHA256,
DIGEST_SHA384,
DIGEST_SHA512,
DIGEST_RIPEMD160
} digests_t;
static const char *digest_names[] = {
"md5",
"sha1",
"sha256",
"sha384",
"sha512",
"ripemd160",
NULL
};
int init_openssl(void)
{
static int initialized = 0;
if (!initialized) {
initialized = 1;
OpenSSL_add_all_digests();
}
return 0;
}
static int openssl_hash (void *data, int size, char *key,
int sizep, const char *passphrase)
{
int alg = *((int *) data);
int round, i;
unsigned int len;
unsigned char buf[EVP_MAX_MD_SIZE];
const EVP_MD *md;
EVP_MD_CTX ctx;
md = EVP_get_digestbyname(digest_names[alg]);
if (md == NULL)
return -1;
/*switch (alg) {
case DIGEST_MD5:
md = EVP_md5();
break;
case DIGEST_SHA1:
md = EVP_sha1();
break;
case DIGEST_SHA256:
md = EVP_sha256();
break;
case DIGEST_SHA384:
md = EVP_sha384();
break;
case DIGEST_SHA512:
md = EVP_sha512();
break;
case DIGEST_RIPEMD160:
md = EVP_ripemd160();
break;
}*/
for(round = 0; size; round++) {
if (!EVP_DigestInit(&ctx, md))
return -1;
/* hack from hashalot to avoid null bytes in key */
for(i = 0; i < round; i++)
if (!EVP_DigestUpdate(&ctx, "A", 1))
return -1;
if (!EVP_DigestUpdate(&ctx, passphrase, sizep))
return -1;
if (!EVP_DigestFinal(&ctx, buf, &len))
return -1;
len = (len > (unsigned int) size) ?
(unsigned int) size : len;
memcpy(key, buf, len);
key += len;
size -= len;
}
memset(buf, 0x00, EVP_MAX_MD_SIZE);
return 0;
}
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);
}
static struct hash_type *openssl_get_hashes(void)
{
struct hash_type *hashes;
int size = 0;
int i = 0;
while (digest_names[i])
i++;
size = 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;
}
/* OpenSSL 1.x provides API to discover this list in a proper way */
i = 0;
while (digest_names[i]) {
hashes[i].name = strdup(digest_names[i]);
if(!hashes[i].name)
goto err;
hashes[i].private = malloc(sizeof(int));
if(!hashes[i].private)
goto err;
*((int *) hashes[i].private) = i;
hashes[i].fn = openssl_hash;
i++;
}
hashes[i].name = NULL;
hashes[i].private = NULL;
hashes[i].fn = NULL;
return hashes;
err:
openssl_free_hashes(hashes);
return NULL;
}
struct hash_backend hash_openssl_backend = {
.name = "openssl",
.get_hashes = openssl_get_hashes,
.free_hashes = openssl_free_hashes
};
^ 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.