This patch makes the minimal changes necessary to enable passphrase key escrow and key recovery via a SOAP client/server mechanism. This is currently at the proof-of-concept level of implementation; there is ample opportunity to add features. You need Python and SWIG installed to build the libecryptfs SWIG component. Run key-escrow-server, and then run escrow-passphrase.py [passphrase] to escrow the key and retrieve-passphrase.py [sig] to fetch the key from the server and put it in your keyring, all via localhost. There are all kinds of opportunities to make this useful and secure, such as stunnel for client-server communications, some kind of authentication mechanism, and the ability to specify the remote server and storage location. This patch just gives a convenient base from which to flesh out a real key escrow capability.
Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]> configure.ac | 38 +++++++ m4/ac_pkg_swig.m4 | 59 +++++++++++ m4/ac_python_devel.m4 | 182 +++++++++++++++++++++++++++++++++++++ m4/swig_python.m4 | 7 + src/Makefile.am | 2 src/daemon/main.c | 6 - src/escrow/escrow-passphrase.py | 55 +++++++++++ src/escrow/key-escrow-server | 86 +++++++++++++++++ src/escrow/retrieve-passphrase.py | 39 +++++++ src/include/ecryptfs.h | 16 ++- src/libecryptfs-swig/Makefile.am | 16 +++ src/libecryptfs-swig/libecryptfs.i | 17 +++ src/libecryptfs/Makefile.am | 2 src/libecryptfs/ecryptfs-stat.c | 2 src/libecryptfs/key_management.c | 178 +++++++++++++++++++++++++++++------- src/libecryptfs/main.c | 9 + 16 files changed, 668 insertions(+), 46 deletions(-) --- diff --git a/configure.ac b/configure.ac index 1faef7a..ecc976f 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,11 @@ AC_CONFIG_SRCDIR([src/libecryptfs]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) +AC_DISABLE_STATIC +AM_PATH_PYTHON(2.5) +AC_PROG_SWIG(1.3.31) +SWIG_PYTHON + LIBECRYPTFS_LT_CURRENT="0" LIBECRYPTFS_LT_REVISION="0" LIBECRYPTFS_LT_AGE="0" @@ -26,6 +31,13 @@ AC_SUBST([LIBECRYPTFS_LT_REVISION]) AC_SUBST([LIBECRYPTFS_LT_AGE]) AC_ARG_ENABLE( + [pywrap], + [AS_HELP_STRING([--disable-pywrap],[Build libecryptfs Python wrappers])], + , + [enable_pywrap="detect"] +) + +AC_ARG_ENABLE( [openssl], [AS_HELP_STRING([--disable-openssl],[Build OpenSSL key module])], , @@ -221,6 +233,30 @@ CFLAGS="${CFLAGS} ${OPENSSL_CFLAGS}" AC_CHECK_HEADER([openssl/rsa.h],, [have_openssl="no"]) CFLAGS="${OLD_CFLAGS}" +have_python="no" +have_swig="no" + +if test "x${PYTHON_VERSION}" != "x" ; then + have_python="yes" +fi + +if test "x${SWIG}" != "x" ; then + have_swig="yes" +fi + +if test "${enable_pywrap}" = "detect" ; then + if test "${have_python}" = "yes" ; then + if test "${have_swig}" = "yes" ; then + enable_pywrap="yes" + fi + fi +fi + +if test "${enable_pywrap}" = "yes" ; then + test "${have_python}" != "yes" && AC_MSG_ERROR([Python not found]) + test "${have_swig}" != "yes" && AC_MSG_ERROR([SWIG not found]) +fi + test "${enable_openssl}" = "detect" && enable_openssl="${have_openssl}" if test "${enable_openssl}" = "yes" ; then @@ -307,6 +343,7 @@ AM_CONDITIONAL([BUILD_PKCS11_HELPER], [test "${enable_pkcs11_helper}" = "yes"]) AM_CONDITIONAL([BUILD_TSPI], [test "${enable_tspi}" = "yes"]) AM_CONDITIONAL([BUILD_GPG], [test "${enable_gpg}" = "yes"]) AM_CONDITIONAL([BUILD_PAM], [test "${enable_pam}" = "yes"]) +AM_CONDITIONAL([BUILD_PYWRAP], [test "${enable_pywrap}" = "yes"]) AM_CONDITIONAL([BUILD_GUI], [test "${enable_gui}" = "yes"]) AM_CONDITIONAL([BUILD_DOCS], [test "${enable_docs}" = "yes"]) AM_CONDITIONAL([BUILD_DOCS_GEN], [test "${enable_docs_gen}" = "yes"]) @@ -341,6 +378,7 @@ AC_CONFIG_FILES([ doc/manpage/Makefile src/pam_ecryptfs/Makefile src/libecryptfs/libecryptfs.pc + src/libecryptfs-swig/Makefile ]) AC_OUTPUT diff --git a/m4/ac_pkg_swig.m4 b/m4/ac_pkg_swig.m4 new file mode 100644 index 0000000..b5130ad --- /dev/null +++ b/m4/ac_pkg_swig.m4 @@ -0,0 +1,59 @@ +AC_DEFUN([AC_PROG_SWIG],[ + AC_PATH_PROG([SWIG],[swig]) + if test -z "$SWIG" ; then + AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org]) + SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false' + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + if test $available_major -ne $required_major \ + -o $available_minor -ne $required_minor \ + -o $available_patch -lt $required_patch ; then + AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org]) + SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' + else + AC_MSG_NOTICE([SWIG executable is '$SWIG']) + SWIG_LIB=`$SWIG -swiglib` + AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB']) + fi + else + AC_MSG_WARN([cannot determine SWIG version]) + SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/m4/ac_python_devel.m4 b/m4/ac_python_devel.m4 new file mode 100644 index 0000000..574da49 --- /dev/null +++ b/m4/ac_python_devel.m4 @@ -0,0 +1,182 @@ +AC_DEFUN([AC_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # + AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + + AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) + if test -z "$PYTHON"; then + AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) + PYTHON_VERSION="" + fi + + # + # Check for a version of Python >= 2.1.0 + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[[0]]; \ + print ver >= '2.1.0'"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([ +This version of the AC@&[EMAIL PROTECTED] macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. +]) + else + AC_MSG_RESULT([skip at user request]) + fi + else + AC_MSG_RESULT([yes]) + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[[0]]; \ + print ver $1"` + if test "$ac_supports_python_ver" = "True"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See ``configure --help'' for reference. +]) + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot import Python module "distutils". +Please check your Python installation. The error was: +$ac_distutils_result]) + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_inc();"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + AC_MSG_RESULT([$PYTHON_CPPFLAGS]) + AC_SUBST([PYTHON_CPPFLAGS]) + + # + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + py_version=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print join(get_config_vars('VERSION'))"` + if test "$py_version" == "[None]"; then + if test -n "$PYTHON_VERSION"; then + py_version=$PYTHON_VERSION + else + py_version=`$PYTHON -c "import sys; \ + print sys.version[[:3]]"` + fi + fi + + PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print '-L' + get_python_lib(0,1), \ + '-lpython';"`$py_version + fi + AC_MSG_RESULT([$PYTHON_LDFLAGS]) + AC_SUBST([PYTHON_LDFLAGS]) + + # + # Check for site packages + # + AC_MSG_CHECKING([for Python site-packages path]) + if test -z "$PYTHON_SITE_PKG"; then + PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_lib(0,0);"` + fi + AC_MSG_RESULT([$PYTHON_SITE_PKG]) + AC_SUBST([PYTHON_SITE_PKG]) + + # + # libraries which must be linked in when embedding + # + AC_MSG_CHECKING(python extra libraries) + if test -z "$PYTHON_EXTRA_LIBS"; then + PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LOCALMODLIBS'), conf('LIBS')"` + fi + AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) + AC_SUBST(PYTHON_EXTRA_LIBS) + + # + # linking flags needed when embedding + # + AC_MSG_CHECKING(python extra linking flags) + if test -z "$PYTHON_EXTRA_LDFLAGS"; then + PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LINKFORSHARED')"` + fi + AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) + AC_SUBST(PYTHON_EXTRA_LDFLAGS) + + # + # final check to see if everything compiles alright + # + AC_MSG_CHECKING([consistency of all components of python development environment]) + AC_LANG_PUSH([C]) + # save current global flags + LIBS="$ac_save_LIBS $PYTHON_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" + AC_TRY_LINK([ + #include <Python.h> + ],[ + Py_Initialize(); + ],[pythonexists=yes],[pythonexists=no]) + + AC_MSG_RESULT([$pythonexists]) + + if test ! "$pythonexists" = "yes"; then + PYTHON_VERSION="" + fi + AC_LANG_POP + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + # + # all done! + # +]) diff --git a/m4/swig_python.m4 b/m4/swig_python.m4 new file mode 100644 index 0000000..3647e54 --- /dev/null +++ b/m4/swig_python.m4 @@ -0,0 +1,7 @@ +AC_DEFUN([SWIG_PYTHON],[ + AC_REQUIRE([AC_PROG_SWIG]) + AC_REQUIRE([AC_PYTHON_DEVEL]) + test "x$1" != "xno" || swig_shadow=" -noproxy" + AC_SUBST([SWIG_PYTHON_OPT],[-python$swig_shadow]) + AC_SUBST([SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +]) diff --git a/src/Makefile.am b/src/Makefile.am index 2641f61..f7dad6a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,4 +10,4 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in -SUBDIRS = key_mod libecryptfs utils daemon include pam_ecryptfs +SUBDIRS = key_mod libecryptfs utils daemon include pam_ecryptfs libecryptfs-swig diff --git a/src/daemon/main.c b/src/daemon/main.c index e33f708..ba0a439 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -30,12 +30,12 @@ #include <fcntl.h> #include <getopt.h> #include <pthread.h> +#include <libgen.h> #include <sys/wait.h> #include <sys/resource.h> #include "config.h" #include "../include/ecryptfs.h" - static char *pidfile = NULL; static char *prompt_prog = NULL; @@ -231,8 +231,8 @@ void sigterm_handler(int sig) pthread_mutex_unlock(&mctx_mux); } -void usage(const char * const me, const struct option * const options, - const char * const short_options) +void usage(const char *const me, const struct option *const options, + const char *const short_options) { const struct option *opt; diff --git a/src/escrow/escrow-passphrase.py b/src/escrow/escrow-passphrase.py new file mode 100644 index 0000000..0f3968e --- /dev/null +++ b/src/escrow/escrow-passphrase.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import sys +import getopt +import base64 +from ZSI.client import Binding +import libecryptfs + +__doc__ = ''' +Usage: escrow-passphrase.py <-v|--verbose> <[salt]> [passphrase] +''' + +def main(): + verbosity = 0 + default_salt_hex = "0011223344556677" + try: + opts, args = getopt.getopt(sys.argv[1:], "hv", ["help", "verbose"]) + except getopt.error, msg: + print msg + print "for help use --help" + sys.exit(2) + for o, a in opts: + if o in ("-h", "--help"): + print __doc__ + sys.exit(0) + elif o in ("-v", "--verbose"): + verbosity = 1 + salt_bytes = [] + if len(args) < 1 or len(args) > 2: + print "invalid number of arguments" + print "for help use --help" + sys.exit(2) + if len(args) == 1: + salt_hex = default_salt_hex + passphrase_charstr = args[0] + if len(args) == 2: + salt_hex = args[0] + passphrase_charstr = args[1] + if len(salt_hex) != 16: + print "Salt value provided is [%s], which is [%d] characters long. The salt must be comprised of [%d] hexidecimal characters." % (salt_hex, len(salt_hex), 16) + for i in range(0, 16, 2): + salt_bytes.append(chr(int(salt_hex[i:i+2], 16))) + salt_charstr = "" + for sb in salt_bytes: + salt_charstr = "%s%c" % (salt_charstr, sb) + blob = libecryptfs.ecryptfs_passphrase_blob(salt_charstr, \ + passphrase_charstr) + sig = libecryptfs.ecryptfs_passphrase_sig_from_blob(blob) + b = Binding(url="http://127.0.0.1:8080") + b64sig = base64.b64encode(sig) + b64blob = base64.b64encode(blob) + b.store_key_blob([b64sig, b64blob]) + +if __name__ == "__main__": + main() diff --git a/src/escrow/key-escrow-server b/src/escrow/key-escrow-server new file mode 100644 index 0000000..ceb4373 --- /dev/null +++ b/src/escrow/key-escrow-server @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +import sys +import getopt +import base64 +from ZSI import dispatch + +default_port = 8080 +default_conf_file_full_path = "/etc/key-escrow-server.conf" + +__doc__ = ''' +Usage: key-escrow-server <-v|--verbose> <-c [configuration file]> \ + <-p [listen port]> <-k [keystore directory]> +''' + +def hello(): + return "Hello, world" + +def skb(args): + return 0 + +def store_key_blob(args): + args_items = args.items() + if len(args_items[0][1]) == 24: + b64sig = args_items[0][1] + b64blob = args_items[1][1] + else: + b64sig = args_items[1][1] + b64blob = args_items[0][1] + sig = base64.b64decode(b64sig).rstrip('\0') + blob = base64.b64decode(b64blob) + filename = unicode(sig) + fh = open(filename, "w") + fh.write(b64blob) + fh.close() + return 0 + +def fetch_key_blob(args): + b64sig = args + sig = base64.b64decode(b64sig) + filename = "%s" % sig + fh = open(filename, "r") + b64blob = fh.read() + fh.close() + return b64blob + +class ServerStat: + def __init__(self, verbosity=0, port=default_port, \ + conf_file_full_path=default_conf_file_full_path): + self.port = port + return None + +class Server: + def __init__(self, server_stat): + self.server_stat = server_stat + return None + + def run(self): + print "Server initialized" + print "Listening on port [%d]" % self.server_stat.port + dispatch.AsServer(port=8080, rpc=True) + +def main(): + server_stat = ServerStat() + try: + opts, args = getopt.getopt(sys.argv[1:], "hvp:", ["help", "verbose", \ + "port="]) + except getopt.error, msg: + print msg + print "for help use --help" + sys.exit(2) + for o, a in opts: + if o in ("-h", "--help"): + print __doc__ + sys.exit(0) + elif o in ("-p", "--port"): + server_stat.port = a + elif o in ("-v", "--verbose"): + server_stat.verbosity = 1 + for arg in args: + print "Ignoring command line parameter: [%s]" % arg + server = Server(server_stat) + server.run() + +if __name__ == "__main__": + main() diff --git a/src/escrow/retrieve-passphrase.py b/src/escrow/retrieve-passphrase.py new file mode 100644 index 0000000..357aacb --- /dev/null +++ b/src/escrow/retrieve-passphrase.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import sys +import getopt +from ZSI.client import Binding +import base64 +import libecryptfs + +__doc__ = ''' +Usage: escrow-passphrase.py <-v|--verbose> [sig] +''' + +def main(): + verbosity = 0 + try: + opts, args = getopt.getopt(sys.argv[1:], "hv", ["help", "verbose"]) + except getopt.error, msg: + print msg + print "for help use --help" + sys.exit(2) + for o, a in opts: + if o in ("-h", "--help"): + print __doc__ + sys.exit(0) + elif o in ("-v", "--verbose"): + verbosity = 1 + if len(args) != 1: + print "invalid number of arguments" + print "for help use --help" + sys.exit(2) + sig = args[0] + b = Binding(url="http://127.0.0.1:8080") + b64sig = base64.b64encode(sig) + b64blob = b.fetch_key_blob(b64sig) + blob = base64.b64decode(b64blob) + libecryptfs.ecryptfs_add_blob_to_keyring(blob, sig) + +if __name__ == "__main__": + main() diff --git a/src/include/ecryptfs.h b/src/include/ecryptfs.h index b18baa6..7f39dca 100644 --- a/src/include/ecryptfs.h +++ b/src/include/ecryptfs.h @@ -481,6 +481,11 @@ struct ecryptfs_crypt_stat_user { struct ecryptfs_auth_tok_list *ptr_to_auth_tok_list_head; }; +typedef struct binary_data { + int size; + unsigned char *data; +} binary_data; + #define ECRYPTFS_DEFAULT_MESSAGING_TYPE ECRYPTFS_MESSAGING_TYPE_NETLINK int ecryptfs_get_kernel_ciphers(struct cipher_descriptor *cd_head); @@ -531,9 +536,8 @@ int parse_packet(struct ecryptfs_ctx *ctx, struct ecryptfs_message **reply); int ecryptfs_find_key_mod(struct ecryptfs_key_mod **key_mod, struct ecryptfs_ctx *ctx, char *key_mod_alias); -int -generate_passphrase_sig(char *passphrase_sig, char *passphrase, char *salt, - char *session_key_encryption_key); +int generate_passphrase_sig(char *passphrase_sig, char *fekek, char *salt, + char *passphrase); int generate_payload(struct ecryptfs_auth_tok *auth_tok, char *passphrase_sig, char *salt, char *session_key_encryption_key); @@ -600,5 +604,11 @@ int ecryptfs_run_miscdev_daemon(struct ecryptfs_miscdev_ctx *miscdev_ctx); struct ecryptfs_ctx_ops *cryptfs_get_ctx_opts(void); int ecryptfs_parse_stat(struct ecryptfs_crypt_stat_user *crypt_stat, char *buf, size_t buf_size); +binary_data ecryptfs_passphrase_blob(char *salt, char *passphrase); +binary_data ecryptfs_passphrase_sig_from_blob(char *blob); +int ecryptfs_add_passphrase_blob_to_keyring(char *blob, char *sig); +int ecryptfs_add_auth_tok_to_keyring(struct ecryptfs_auth_tok *auth_tok, + char *auth_tok_sig); +int ecryptfs_add_blob_to_keyring(char *blob, char *sig); #endif diff --git a/src/libecryptfs-swig/Makefile.am b/src/libecryptfs-swig/Makefile.am new file mode 100644 index 0000000..5f41eb3 --- /dev/null +++ b/src/libecryptfs-swig/Makefile.am @@ -0,0 +1,16 @@ +if BUILD_PYWRAP + +BUILT_SOURCES = $(srcdir)/libecryptfs_wrap.c +SWIG_SOURCES = libecryptfs.i + +pkgpython_PYTHON = libecryptfs.py +pkgpyexec_LTLIBRARIES = _libecryptfs.la +_libecryptfs_la_SOURCES = $(srcdir)/libecryptfs_wrap.c $(SWIG_SOURCES) +_libecryptfs_la_CFLAGS = $(SWIG_PYTHON_CPPFLAGS) -I$(top_srcdir)/src/include +_libecryptfs_la_LDFLAGS = -module +_libecryptfs_la_LIBADD = ../libecryptfs/.libs/libecryptfs.la + +$(srcdir)/libecryptfs_wrap.c : $(SWIG_SOURCES) + $(SWIG) $(SWIG_PYTHON_OPT) -I$(top_srcdir)/src/include -o $@ $< + +endif diff --git a/src/libecryptfs-swig/libecryptfs.i b/src/libecryptfs-swig/libecryptfs.i new file mode 100644 index 0000000..19f79a0 --- /dev/null +++ b/src/libecryptfs-swig/libecryptfs.i @@ -0,0 +1,17 @@ +%module libecryptfs +%{ +#include "../include/ecryptfs.h" +extern binary_data ecryptfs_passphrase_blob(char *salt, char *passphrase); +extern binary_data ecryptfs_passphrase_sig_from_blob(char *blob); +extern int ecryptfs_add_blob_to_keyring(char *blob, char *sig); +%} + +#include "../include/ecryptfs.h" + +%typemap(out) binary_data { + $result = PyString_FromStringAndSize($1.data,$1.size); +} + +extern binary_data ecryptfs_passphrase_blob(char *salt, char *passphrase); +extern binary_data ecryptfs_passphrase_sig_from_blob(char *blob); +extern int ecryptfs_add_blob_to_keyring(char *blob, char *sig); diff --git a/src/libecryptfs/Makefile.am b/src/libecryptfs/Makefile.am index 064ebb4..9c61980 100644 --- a/src/libecryptfs/Makefile.am +++ b/src/libecryptfs/Makefile.am @@ -1,6 +1,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in lib_LTLIBRARIES = libecryptfs.la + pkgconfig_DATA = libecryptfs.pc libecryptfs_la_SOURCES = \ @@ -18,6 +19,7 @@ libecryptfs_la_SOURCES = \ key_mod.c \ ecryptfs-stat.c \ $(top_srcdir)/src/key_mod/ecryptfs_key_mod_passphrase.c + libecryptfs_la_LDFLAGS = \ -version-info @LIBECRYPTFS_LT_CURRENT@:@LIBECRYPTFS_LT_REVISION@:@LIBECRYPTFS_LT_AGE@ \ -no-undefined diff --git a/src/libecryptfs/ecryptfs-stat.c b/src/libecryptfs/ecryptfs-stat.c index dd9a80b..4726421 100644 --- a/src/libecryptfs/ecryptfs-stat.c +++ b/src/libecryptfs/ecryptfs-stat.c @@ -277,7 +277,7 @@ static int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat_user *crypt_stat out_wipe_list: auth_tok_list = crypt_stat->ptr_to_auth_tok_list_head; while (auth_tok_list) { - struct ecryptfs_auth_tok *next_auth_tok_list; + struct ecryptfs_auth_tok_list *next_auth_tok_list; next_auth_tok_list = auth_tok_list->next; free(auth_tok_list->auth_tok); diff --git a/src/libecryptfs/key_management.c b/src/libecryptfs/key_management.c index 2c88357..c270b85 100644 --- a/src/libecryptfs/key_management.c +++ b/src/libecryptfs/key_management.c @@ -42,26 +42,99 @@ #endif /** - * This is the common functionality used to put a password generated key into - * the keyring, shared by both non-interactive and interactive signature - * generation code. - * - * Returns 0 on add, 1 on pre-existed, negative on failure. + * @auth_tok: (out) This function will allocate; callee must free + * @auth_tok_sig: (out) Allocated memory this function fills in: + (ECRYPTFS_SIG_SIZE_HEX + 1) + * @fekek: (out) Allocated memory this function fills in: ECRYPTFS_MAX_KEY_BYTES + * @salt: (in) salt: ECRYPTFS_SALT_SIZE + * @passphrase: (in) passphrase: ECRYPTFS_MAX_PASSPHRASE_BYTES */ -int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, - char *salt) +int ecryptfs_generate_passphrase_auth_tok(struct ecryptfs_auth_tok **auth_tok, + char *auth_tok_sig, char *fekek, + char *salt, char *passphrase) { int rc; - char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; - struct ecryptfs_auth_tok *auth_tok = NULL; - if ((rc = generate_passphrase_sig(auth_tok_sig, passphrase, salt, - session_key_encryption_key))) { + *auth_tok = NULL; + rc = generate_passphrase_sig(auth_tok_sig, fekek, salt, passphrase); + if (rc) { syslog(LOG_ERR, "Error generating passphrase signature; " "rc = [%d]\n", rc); rc = (rc < 0) ? rc : rc * -1; goto out; } + *auth_tok = malloc(sizeof(struct ecryptfs_auth_tok)); + if (!*auth_tok) { + syslog(LOG_ERR, "Unable to allocate memory for auth_tok\n"); + rc = -ENOMEM; + goto out; + } + rc = generate_payload(*auth_tok, auth_tok_sig, salt, fekek); + if (rc) { + syslog(LOG_ERR, "Error generating payload for auth tok key; " + "rc = [%d]\n", rc); + rc = (rc < 0) ? rc : rc * -1; + goto out; + } +out: + return rc; +} + +/** + * ecryptfs_passphrase_sig_from_blob + * @blob: Byte array of struct ecryptfs_auth_tok + * + * SWIG support function. + */ +binary_data ecryptfs_passphrase_sig_from_blob(char *blob) +{ + struct ecryptfs_auth_tok *auth_tok; + binary_data bd; + + auth_tok = (struct ecryptfs_auth_tok *)blob; + bd.size = (ECRYPTFS_PASSWORD_SIG_SIZE + 1); + bd.data = auth_tok->token.password.signature; + return bd; +} + +/** + * ecryptfs_passphrase_blob + * @salt: Hexadecimal representation of the salt value + * @passphrase: Passphrase + * + * SWIG support function. + */ +binary_data ecryptfs_passphrase_blob(char *salt, char *passphrase) +{ + char *blob; + struct ecryptfs_auth_tok *auth_tok; + char auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1]; + char fekek[ECRYPTFS_MAX_KEY_BYTES]; + binary_data bd; + int rc; + + memset(&bd, 0, sizeof(bd)); + rc = ecryptfs_generate_passphrase_auth_tok(&auth_tok, auth_tok_sig, + fekek, salt, passphrase); + if (rc) { + syslog(LOG_ERR, "%s: Error attempting to generate passphrase " + "authentication token blob; rc = [%d]\n", __FUNCTION__, + rc); + blob = NULL; + goto out; + } + blob = (char *)auth_tok; + bd.size = sizeof(struct ecryptfs_auth_tok); + bd.data = blob; +out: + return bd; +} + +int ecryptfs_add_auth_tok_to_keyring(struct ecryptfs_auth_tok *auth_tok, + char *auth_tok_sig) +{ + int rc; + rc = (int)keyctl_search(KEY_SPEC_USER_KEYRING, "user", auth_tok_sig, 0); if (rc != -1) { /* we already have this key in keyring; we're done */ rc = 1; @@ -75,19 +148,6 @@ int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, rc = (errnum < 0) ? errnum : errnum * -1; goto out; } - auth_tok = malloc(sizeof(struct ecryptfs_auth_tok)); - if (!auth_tok) { - syslog(LOG_ERR, "Unable to allocate memory for auth_tok\n"); - rc = -ENOMEM; - goto out; - } - if ((rc = generate_payload(auth_tok, auth_tok_sig, salt, - session_key_encryption_key))) { - syslog(LOG_ERR, "Error generating payload for auth tok key; " - "rc = [%d]\n", rc); - rc = (rc < 0) ? rc : rc * -1; - goto out_wipe; - } rc = add_key("user", auth_tok_sig, (void *)auth_tok, sizeof(struct ecryptfs_auth_tok), KEY_SPEC_USER_KEYRING); if (rc == -1) { @@ -96,13 +156,63 @@ int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, syslog(LOG_ERR, "Error adding key with sig [%s]; rc = [%d] " "\%s\"\n", auth_tok_sig, rc, strerror(errnum)); rc = (errnum < 0) ? errnum : errnum * -1; - goto out_wipe; + goto out; } rc = 0; -out_wipe: - memset(auth_tok, 0, sizeof(auth_tok)); out: - free(auth_tok); + return rc; +} + +/** + * ecryptfs_add_blob_to_keyring + * @blob: Byte array containing struct ecryptfs_auth_tok + * @sig: Hexadecimal representation of the auth tok signature + * + * SWIG support function. + */ +int ecryptfs_add_blob_to_keyring(char *blob, char *sig) +{ + int rc; + + rc = ecryptfs_add_auth_tok_to_keyring((struct ecryptfs_auth_tok *)blob, + sig); + return rc; +} + +/** + * This is the common functionality used to put a password generated key into + * the keyring, shared by both non-interactive and interactive signature + * generation code. + * + * Returns 0 on add, 1 on pre-existed, negative on failure. + */ +int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, + char *salt) +{ + int rc; + char fekek[ECRYPTFS_MAX_KEY_BYTES]; + struct ecryptfs_auth_tok *auth_tok = NULL; + + rc = ecryptfs_generate_passphrase_auth_tok(&auth_tok, auth_tok_sig, + fekek, salt, passphrase); + if (rc) { + syslog(LOG_ERR, "%s: Error attempting to generate the " + "passphrase auth tok payload; rc = [%d]\n", + __FUNCTION__, rc); + goto out; + } + rc = ecryptfs_add_auth_tok_to_keyring(auth_tok, auth_tok_sig); + if (rc) { + syslog(LOG_ERR, "%s: Error adding auth tok with sig [%s] to " + "the keyring; rc = [%d]\n", __FUNCTION__, auth_tok_sig, + rc); + goto out; + } +out: + if (auth_tok) { + memset(auth_tok, 0, sizeof(auth_tok)); + free(auth_tok); + } return rc; } @@ -131,9 +241,9 @@ int ecryptfs_wrap_passphrase(char *filename, char *wrapping_passphrase, rc = -EIO; goto out; } - if ((rc = generate_passphrase_sig(wrapping_auth_tok_sig, - wrapping_passphrase, wrapping_salt, - wrapping_key))) { + rc = generate_passphrase_sig(wrapping_auth_tok_sig, wrapping_key, + wrapping_salt, wrapping_passphrase); + if (rc) { syslog(LOG_ERR, "Error generating passphrase signature; " "rc = [%d]\n", rc); rc = (rc < 0) ? rc : rc * -1; @@ -233,9 +343,9 @@ int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, char *filename, ssize_t size; int rc; - if ((rc = generate_passphrase_sig(wrapping_auth_tok_sig, - wrapping_passphrase, wrapping_salt, - wrapping_key))) { + rc = generate_passphrase_sig(wrapping_auth_tok_sig, wrapping_key, + wrapping_salt, wrapping_passphrase); + if (rc) { syslog(LOG_ERR, "Error generating passphrase signature; " "rc = [%d]\n", rc); rc = (rc < 0) ? rc : rc * -1; diff --git a/src/libecryptfs/main.c b/src/libecryptfs/main.c index 2a9cac1..2925e09 100644 --- a/src/libecryptfs/main.c +++ b/src/libecryptfs/main.c @@ -95,6 +95,7 @@ int do_hash(char *src, int src_size, char *dst, int algo) /** * TODO: We need to support more hash algs + * @fekek: ECRYPTFS_MAX_KEY_BYTES bytes of allocated memory * * @passphrase A NULL-terminated char array * @@ -105,11 +106,11 @@ int do_hash(char *src, int src_size, char *dst, int algo) * */ int -generate_passphrase_sig(char *passphrase_sig, char *passphrase, char *salt, - char *session_key_encryption_key) +generate_passphrase_sig(char *passphrase_sig, char *fekek, + char *salt, char *passphrase) { char salt_and_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES - + ECRYPTFS_SALT_SIZE]; + + ECRYPTFS_SALT_SIZE]; int passphrase_size; int alg = GCRY_MD_SHA512; int dig_len = SHA512_DIGEST_LENGTH; @@ -137,7 +138,7 @@ generate_passphrase_sig(char *passphrase_sig, char *passphrase, char *salt, return rc; } } - memcpy(session_key_encryption_key, buf, ECRYPTFS_MAX_KEY_BYTES); + memcpy(fekek, buf, ECRYPTFS_MAX_KEY_BYTES); if ((rc = do_hash(buf, dig_len, buf, alg))) { return rc; }
pgpXECE3SxaCp.pgp
Description: PGP signature
------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________ eCryptfs-devel mailing list eCryptfs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel