[Gluster-devel] [PATCH BUG:393 07/10] transport/encryption: add NaCl encryptor
Corentin Chary
corentin.chary at gmail.com
Wed Nov 18 11:13:59 UTC 2009
This encryption plugin is based on libnacl
<http://nacl.cace-project.eu/secretbox.html> and use
crypto_secrebox/crypto_secretbox_open.
Currently libnacl doesn't provide any shared library, to
we need to link against libnacl.a. This may not work on
x86_64, to fix that :
- add -fPIC to okcompilers/c
- move the content of crypto_onetimeauth/poly1305/amd64/constants.s
to crypto_onetimeauth/poly1305/amd64/auth.s
To enable NaCl on configure:
./configure --enable-nacl=yes --with-nacl-dir=/path/to/nacl/build/localhost
Signed-off-by: Corentin Chary <corentin.chary at gmail.com>
---
configure.ac | 68 +++++++-
libglusterfs/src/protocol.h | 9 +
transport/encryption/Makefile.am | 2 +-
transport/encryption/nacl/Makefile.am | 1 +
transport/encryption/nacl/src/Makefile.am | 16 ++
transport/encryption/nacl/src/nacl.c | 275 +++++++++++++++++++++++++++++
transport/encryption/nacl/src/nacl.h | 39 ++++
7 files changed, 407 insertions(+), 3 deletions(-)
create mode 100644 transport/encryption/nacl/Makefile.am
create mode 100644 transport/encryption/nacl/src/Makefile.am
create mode 100644 transport/encryption/nacl/src/nacl.c
create mode 100644 transport/encryption/nacl/src/nacl.h
diff --git a/configure.ac b/configure.ac
index ef455fd..2e318b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -112,6 +112,8 @@ AC_CONFIG_FILES([Makefile
transport/ib-verbs/Makefile
transport/ib-verbs/src/Makefile
transport/encryption/Makefile
+ transport/encryption/nacl/Makefile
+ transport/encryption/nacl/src/Makefile
auth/Makefile
auth/addr/Makefile
auth/addr/src/Makefile
@@ -163,7 +165,7 @@ fi
AC_CHECK_TOOL([LD],[ld])
AC_CHECK_LIB([pthread], [pthread_mutex_init], , AC_MSG_ERROR([Posix threads library is required to build glusterfs]))
-
+
AC_CHECK_FUNC([dlopen], [has_dlopen=yes], AC_CHECK_LIB([dl], [dlopen], , AC_MSG_ERROR([Dynamic linking library required to build glusterfs])))
@@ -244,6 +246,67 @@ fi
AC_SUBST(FUSERMOUNT_SUBDIR)
#end FUSERMOUNT section
+# OPENSSL section
+AC_CHECK_LIB([ssl], [EVP_BytesToKey], [HAVE_OPENSSL="yes"], [HAVE_OPENSSL="no"])
+
+if test "x$HAVE_OPENSSL" = "xyes"; then
+ AC_DEFINE(HAVE_OPENSSL, 1, [found EVP_BytesToKey])
+fi
+# end OPENSSL section
+
+# NACL section
+nacl_arch="unknown"
+case $host_cpu in
+ i*86) nacl_arch="x86";;
+ x86_64) nacl_arch="amd64";;
+ amd64) nacl_arch="amd64";;
+esac
+
+AC_ARG_ENABLE([nacl],
+ AC_HELP_STRING([--disable-nacl],
+ [Do not build the ibverbs transport]))
+AC_ARG_WITH(nacl-dir,
+ [ --with-nacl-dir=DIR nacl installed in DIR @<:@/usr@:>@],
+ [nacl_dir=$withval],
+ [nacl_dir='/usr'])
+
+if test x"$use_nacl" != "xno" -a x"$nacl_arch" = "xunknown" ; then
+ echo "nacl requested but $host_cpu CPU not supported."
+ exit 1
+fi
+
+if test "x$enable_nacl" != "xno" -a "x$HAVE_OPENSSL" = "xyes"; then
+ if test "x$nacl_dir" != "x"; then
+ LDFLAGS="$LDFLAGS -L$nacl_dir/lib/$nacl_arch"
+ AC_CHECK_HEADERS([$nacl_dir/include/$nacl_arch/crypto_secretbox.h])
+ else
+ AC_CHECK_HEADERS([crypto_secretbox.h])
+ fi
+ AC_CHECK_LIB([nacl], [crypto_nacl_base], [HAVE_NACL="yes"], [HAVE_NACL="no"])
+fi
+
+if test "x$enable_nacl" != "xno" -a "x$HAVE_NACL" = "xno"; then
+ echo "nacl requested but not found."
+ exit 1
+fi
+
+BUILD_NACL=no
+if test "x$enable_nacl" != "xno" -a "x$HAVE_NACL" = "xyes"; then
+ NACL_SUBDIR=nacl
+ BUILD_NACL=yes
+ NACL_LIBDIR=${nacl_dir}/lib/${nacl_arch}
+ NACL_INCDIR=${nacl_dir}/include/${nacl_arch}
+ NACL_LDADD=${NACL_LIBDIR}/libnacl.a
+fi
+AC_SUBST(NACL_SUBDIR)
+AC_SUBST(NACL_LIBDIR)
+AC_SUBST(NACL_INCDIR)
+AC_SUBST(NACL_LDADD)
+
+if test "x$HAVE_NACL" = "xyes"; then
+ AC_DEFINE(HAVE_NACL, 1, [found NaCl])
+fi
+# end NACL section
# EPOLL section
AC_ARG_ENABLE([epoll],
@@ -455,7 +518,7 @@ case $host_os in
GF_LDADD="${ARGP_STANDALONE_LDADD}"
if test "x$ac_cv_header_execinfo_h" = "xyes"; then
GF_GLUSTERFS_LDFLAGS="-lexecinfo"
- fi
+ fi
GF_FUSE_LDADD="-liconv -lfuse"
BUILD_LIBGLUSTERFSCLIENT=no
LIBGLUSTERFSCLIENT_SUBDIR=""
@@ -495,6 +558,7 @@ echo "GlusterFS configure summary"
echo "==========================="
echo "FUSE client : $BUILD_FUSE_CLIENT"
echo "Infiniband verbs : $BUILD_IBVERBS"
+echo "NaCl encryption : $BUILD_NACL"
echo "epoll IO multiplex : $BUILD_EPOLL"
echo "Berkeley-DB : $BUILD_BDB"
echo "libglusterfsclient : $BUILD_LIBGLUSTERFSCLIENT"
diff --git a/libglusterfs/src/protocol.h b/libglusterfs/src/protocol.h
index 2341ec8..fe0e420 100644
--- a/libglusterfs/src/protocol.h
+++ b/libglusterfs/src/protocol.h
@@ -964,12 +964,21 @@ typedef struct {
} __attribute__ ((packed)) gf_hdr_rsp_t;
typedef struct {
+ char nonce[32];
+ char crypto_hdr[32];
+ char crypto_vec[32];
+} __attribute__ ((packed)) gf_hdr_nacl_t;
+
+typedef struct {
uint64_t callid;
uint32_t type;
uint32_t op;
uint32_t size;
uint32_t crypto;
union {
+ gf_hdr_nacl_t nacl;
+ } __attribute__ ((packed));
+ union {
gf_hdr_req_t req;
gf_hdr_rsp_t rsp;
} __attribute__ ((packed));
diff --git a/transport/encryption/Makefile.am b/transport/encryption/Makefile.am
index e182a87..cdff0ca 100644
--- a/transport/encryption/Makefile.am
+++ b/transport/encryption/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS =
+SUBDIRS = $(NACL_SUBDIR)
CLEANFILES =
diff --git a/transport/encryption/nacl/Makefile.am b/transport/encryption/nacl/Makefile.am
new file mode 100644
index 0000000..f963eff
--- /dev/null
+++ b/transport/encryption/nacl/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src
\ No newline at end of file
diff --git a/transport/encryption/nacl/src/Makefile.am b/transport/encryption/nacl/src/Makefile.am
new file mode 100644
index 0000000..c6c171a
--- /dev/null
+++ b/transport/encryption/nacl/src/Makefile.am
@@ -0,0 +1,16 @@
+xlator_LTLIBRARIES = nacl.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/transport/encryption
+
+nacl_la_LDFLAGS = -module -avoidversion -lssl
+
+nacl_la_SOURCES = nacl.c
+nacl_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la ${NACL_LIBDIR}/libnacl.a
+
+noinst_HEADERS = nacl.h
+
+AM_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \
+ -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) \
+ -I$(NACL_INCDIR)
+
+CLEANFILES =
+
diff --git a/transport/encryption/nacl/src/nacl.c b/transport/encryption/nacl/src/nacl.c
new file mode 100644
index 0000000..40f7e28
--- /dev/null
+++ b/transport/encryption/nacl/src/nacl.c
@@ -0,0 +1,275 @@
+/*
+ Copyright (c) 2009 commonIT
+ Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <ctype.h>
+#include <sys/uio.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "glusterfs.h"
+#include "xlator.h"
+#include "transport.h"
+#include "logging.h"
+#include "protocol.h"
+#include "iobuf.h"
+
+#include "nacl.h"
+
+#include <openssl/evp.h>
+
+#define NACL_ZERO_BYTES crypto_secretbox_ZEROBYTES
+#define NACL_NONCE_BYTES crypto_secretbox_NONCEBYTES
+
+static char *
+nacl_alloc(transport_crypto_t *this, size_t len, struct iobuf **ref)
+{
+ if (len + NACL_ZERO_BYTES > GF_UNIT_MB) {
+ char *p = CALLOC (1, len + NACL_ZERO_BYTES);
+
+ if (!p)
+ return NULL;
+ return p;
+ } else {
+ *ref = iobuf_get (this->xl->ctx->iobuf_pool);
+ if (!*ref)
+ return NULL;
+ return (*ref)->ptr;
+ }
+}
+
+static void
+nacl_free(struct iobuf *iobuf, struct iobuf *ref, char *ptr)
+{
+ if (ref)
+ iobuf_unref (ref);
+ else if (!iobuf || ptr != iobuf->ptr)
+ FREE (ptr);
+}
+
+static char *
+nacl_join(transport_crypto_t *this, struct iobuf *iobuf,
+ char *buf, size_t len, char *prefix, struct iobuf **iobuf_p)
+{
+ if (len + NACL_ZERO_BYTES > GF_UNIT_MB) {
+ char *p = nacl_alloc(this, len + NACL_ZERO_BYTES, NULL);
+
+ if (!p)
+ return NULL;
+ memcpy(p, prefix, NACL_ZERO_BYTES);
+ if (buf)
+ memcpy(p + NACL_ZERO_BYTES, buf, len);
+ else
+ memcpy(p + NACL_ZERO_BYTES, iobuf->ptr, len);
+ return p;
+ } else if (iobuf) {
+ memmove(iobuf->ptr + NACL_ZERO_BYTES, iobuf->ptr, len);
+ memcpy(iobuf->ptr, prefix, NACL_ZERO_BYTES);
+ return iobuf->ptr;
+ } else {
+ nacl_alloc(this, len, iobuf_p);
+ if (!*iobuf_p)
+ return NULL;
+ memcpy((*iobuf_p)->ptr, prefix, NACL_ZERO_BYTES);
+ memcpy((*iobuf_p)->ptr + NACL_ZERO_BYTES, buf, len);
+ return (*iobuf_p)->ptr;
+ }
+}
+static void
+nacl_split(struct iobuf *iobuf, char *buf, size_t len, char *prefix, char *p)
+{
+ memcpy(prefix, p, NACL_ZERO_BYTES);
+ if (iobuf)
+ /* memmove because p could be iobuf->ptr */
+ memmove(iobuf->ptr, p + NACL_ZERO_BYTES, len);
+ else
+ memcpy(buf, p + NACL_ZERO_BYTES, len);
+}
+
+static int32_t
+__nacl_work (transport_crypto_t *this, struct iobuf *iobuf,
+ char *buf, size_t len, char *prefix,
+ char *nonce, int encrypt)
+{
+ char *orig, *dest;
+ struct iobuf *orig_ref = NULL, *dest_ref = NULL;
+ nacl_private_t *priv;
+ int ret;
+ char n[32];
+
+ priv = this->xl_private;
+ memcpy (n, nonce, NACL_NONCE_BYTES);
+ //memset (n, 0, NACL_NONCE_BYTES);
+ orig = nacl_join (this, iobuf, buf, len, prefix, &orig_ref);
+ dest = nacl_alloc (this, len, &dest_ref);
+ if (!orig || !dest)
+ return -ENOMEM;
+
+ if (encrypt)
+ memset (orig, 0, NACL_ZERO_BYTES);
+
+ if (encrypt)
+ ret = crypto_secretbox ((u_char *)dest, (u_char *)orig,
+ len + NACL_ZERO_BYTES,
+ (u_char *)n, priv->k);
+ else
+ ret = crypto_secretbox_open ((u_char *)dest, (u_char *)orig,
+ len + NACL_ZERO_BYTES,
+ (u_char *)n, priv->k);
+ if (ret)
+ gf_log ("nacl", GF_LOG_ERROR, "error during %s."
+ " Check the passphrase.",
+ encrypt ? "encryption" : "decryption");
+ nacl_split(iobuf, buf, len, prefix, dest);
+
+ nacl_free(iobuf, orig_ref, orig);
+ nacl_free(NULL, dest_ref, dest);
+ return ret;
+}
+
+static int32_t
+nacl_iovec (transport_crypto_t *this, struct iovec *vector, int count,
+ char *prefix, char *nonce)
+{
+ size_t len;
+ int32_t ret;
+ struct iobuf *iobuf;
+
+ if (!vector || !count)
+ return 0;
+
+ iobuf = iobuf_get (this->xl->ctx->iobuf_pool);
+ if (!iobuf)
+ return -ENOMEM;
+ iov_unload (iobuf->ptr, vector, count);
+ len = iov_length (vector, count);
+ ret = __nacl_work (this, iobuf, NULL, len, prefix, nonce, 1);
+ iov_load (vector, count, iobuf->ptr);
+ iobuf_unref (iobuf);
+ return ret;
+}
+
+int32_t
+nacl_encrypt (transport_crypto_t *this, char *hdr, size_t len,
+ struct iovec *vector, int count)
+{
+ int32_t ret = 0;
+ int32_t n;
+ gf_hdr_common_t *h = (gf_hdr_common_t *)hdr;
+ nacl_private_t *priv;
+
+ priv = this->xl_private;
+
+ n = (h->callid << 16) ^ h->size ^ priv->time;
+ memcpy (h->nacl.nonce, (char *)&n, NACL_NONCE_BYTES);
+
+ ret = __nacl_work (this, NULL, gf_param(h), len - GF_HDR_COMMON_SIZE,
+ h->nacl.crypto_hdr, h->nacl.nonce, 1);
+ if (ret)
+ return ret;
+ if (count)
+ ret = nacl_iovec (this, vector, count, h->nacl.crypto_vec,
+ h->nacl.nonce);
+ return ret;
+}
+
+int32_t
+nacl_decrypt (transport_crypto_t *this, char *hdr, size_t len,
+ struct iobuf *iobuf, size_t buflen)
+{
+ int32_t ret = 0;
+ gf_hdr_common_t *h = (gf_hdr_common_t *)hdr;
+
+ ret = __nacl_work (this, NULL, gf_param(h), len - GF_HDR_COMMON_SIZE,
+ h->nacl.crypto_hdr, h->nacl.nonce, 0);
+ if (ret)
+ return ret;
+ if (buflen)
+ ret = __nacl_work (this, iobuf, NULL, buflen,
+ h->nacl.crypto_vec, h->nacl.nonce, 0);
+ return ret;
+}
+
+static void
+nacl_gen_key(nacl_private_t *priv, const char *pass)
+{
+ const EVP_CIPHER *cipher = EVP_aes_256_cbc();
+ const EVP_MD *dgst = EVP_sha1();
+ u_char key[cipher->key_len];
+ u_char iv[cipher->iv_len];
+
+ /* GF_PROTOCOL_VERSION use as salt */
+ EVP_BytesToKey(cipher, dgst,
+ (u_char *)GF_PROTOCOL_VERSION, (u_char *)pass,
+ strlen(pass), 1, key, iv);
+
+ memcpy(priv->k, key, crypto_secretbox_KEYBYTES);
+}
+
+int32_t
+init (transport_crypto_t *crypto)
+{
+ nacl_private_t *priv;
+ char *password;
+ data_t *password_data;
+
+ priv = CALLOC (1, sizeof (*priv));
+ if (!priv)
+ return -ENOMEM;
+
+ crypto->xl_private = priv;
+ crypto->magic = CRYPTO_MAGIC_NACL;
+
+
+ password_data = dict_get (crypto->xl->options,
+ "transport.crypto.passphrase");
+ if (!password_data) {
+ gf_log ("nacl", GF_LOG_ERROR, "no passphrase specified");
+ return -1;
+ }
+
+ password = data_to_str (password_data);
+ nacl_gen_key(priv, password);
+ priv->time = time(NULL);
+
+ gf_log ("nacl", GF_LOG_DEBUG, "nacl transport encryptor loaded");
+ return 0;
+}
+
+void
+fini (transport_crypto_t *crypto)
+{
+ FREE (crypto->xl_private);
+ return;
+}
+
+struct transport_crypto_ops tcops = {
+ .encrypt = nacl_encrypt,
+ .decrypt = nacl_decrypt,
+};
+
+struct volume_options options[] = {
+ { .key = {"transport.crypto.passphrase"},
+ .type = GF_OPTION_TYPE_ANY
+ },
+ { .key = {NULL} },
+};
diff --git a/transport/encryption/nacl/src/nacl.h b/transport/encryption/nacl/src/nacl.h
new file mode 100644
index 0000000..89e8f7a
--- /dev/null
+++ b/transport/encryption/nacl/src/nacl.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (c) 2009 commonIT
+ Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __NACL_H__
+#define __NACL_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <crypto_secretbox.h>
+
+#define CRYPTO_MAGIC_NACL 58443 /* NaCl molar mass :) */
+
+typedef struct {
+ unsigned char k[crypto_secretbox_KEYBYTES];
+ time_t time;
+} nacl_private_t;
+
+
+#endif /* __ROT_13_H__ */
--
1.6.4.4
More information about the Gluster-devel
mailing list