--- systemd-38-r1.orig/work/systemd-38/configure.ac 2012-02-02 02:55:51.748001032 -0800 +++ systemd-38-r1/work/systemd-38/configure.ac 2012-02-16 23:42:26.760047590 -0800 @@ -309,6 +309,27 @@ fi AM_CONDITIONAL(HAVE_LIBCRYPTSETUP, [test "$have_libcryptsetup" = "yes"]) +have_gpgme=no +AC_ARG_ENABLE(gpgme, AS_HELP_STRING([--disable-gpgme], [disable gpgme support])) +if test "x$enable_gpgme" != "xno"; then + AC_CHECK_HEADER([unistd.h], [], [AC_MSG_ERROR([*** unistd.h header not found])]) + AC_CHECK_HEADER([gpgme/gpgme.h], + [AC_DEFINE(HAVE_GPGME, 1, [Define if gpgme is available]) have_gpgme=yes], have_gpgme=no) + if test "x$have_gpgme" = xno -a "x$enable_gpgme" = xyes; then + AC_MSG_ERROR([*** gpgme support requested but header not found]) + fi + AC_CHECK_LIB(gpgme, gpgme_op_decrypt, + [AC_DEFINE(HAVE_GPGME, 1, [Define if gpgme is available]) have_gpgme=yes], have_gpgme=no) + if test "x$have_gpgme" = xno -a "x$enable_gpgme" = xyes; then + AC_MSG_ERROR([*** gpgme support requested but libraries not found]) + fi + GPGME_CFLAGS=`gpgme-config --cflags` + GPGME_LIBS=`gpgme-config --libs` + AC_SUBST(GPGME_CFLAGS) + AC_SUBST(GPGME_LIBS) +fi +AM_CONDITIONAL(HAVE_GPGME, [test "$have_gpgme" = "yes"]) + have_binfmt=no AC_ARG_ENABLE(binfmt, AS_HELP_STRING([--disable-binfmt], [disable binfmt tool])) if test "x$enable_binfmt" != "xno"; then @@ -631,6 +652,7 @@ SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH} Gtk: ${have_gtk} libcryptsetup: ${have_libcryptsetup} + gpgme: ${have_gpgme} tcpwrap: ${have_tcpwrap} PAM: ${have_pam} AUDIT: ${have_audit} --- systemd-38-r1.orig/work/systemd-38/Makefile.am 2012-02-02 02:55:51.748001032 -0800 +++ systemd-38-r1/work/systemd-38/Makefile.am 2012-02-16 23:42:26.764047590 -0800 @@ -1575,10 +1575,12 @@ systemd_cryptsetup_CFLAGS = \ $(AM_CFLAGS) \ $(LIBCRYPTSETUP_CFLAGS) \ + $(GPGME_CFLAGS) \ $(UDEV_CFLAGS) systemd_cryptsetup_LDADD = \ $(LIBCRYPTSETUP_LIBS) \ + $(GPGME_LIBS) \ $(UDEV_LIBS) \ libsystemd-basic.la --- systemd-38-r1.orig/work/systemd-38/src/cryptsetup/cryptsetup.c 2012-02-02 02:55:51.730001038 -0800 +++ systemd-38-r1/work/systemd-38/src/cryptsetup/cryptsetup.c 2012-02-16 23:47:44.289048268 -0800 @@ -23,6 +23,10 @@ #include #include #include +#if HAVE_GPGME +#include +#include +#endif #include #include @@ -38,6 +42,9 @@ static unsigned opt_key_size = 0; static char *opt_hash = NULL; static unsigned opt_tries = 0; +#if HAVE_GPGME +static bool opt_gpg = false; +#endif static bool opt_readonly = false; static bool opt_verify = false; static usec_t opt_timeout = DEFAULT_TIMEOUT_USEC; @@ -97,6 +104,10 @@ opt_readonly = true; else if (streq(option, "verify")) opt_verify = true; +#if HAVE_GPGME + else if (streq(option, "gpg")) + opt_gpg = true; +#endif else if (streq(option, "luks")) opt_type = CRYPT_LUKS1; else if (streq(option, "plain") || @@ -219,6 +230,14 @@ return 0; } +#if HAVE_GPGME +static gpgme_error_t passfunc(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) +{ + write(fd, hook, strlen(hook)); + return 0; +} +#endif + int main(int argc, char *argv[]) { int r = EXIT_FAILURE; struct crypt_device *cd = NULL; @@ -344,7 +363,11 @@ strv_free(passwords); passwords = NULL; - if (!key_file) { + if (!key_file +#if HAVE_GPGME + || (key_file && opt_gpg) +#endif + ) { char *text; char **p; @@ -405,6 +428,12 @@ } strncpy(c, *p, opt_key_size); + +#if HAVE_GPGME + if (opt_gpg) + strncat(c, "\n", opt_key_size-1); +#endif + free(*p); *p = c; } @@ -453,7 +482,11 @@ crypt_get_volume_key_size(cd)*8, argv[3]); - if (key_file) + if (key_file +#if HAVE_GPGME + && !opt_gpg +#endif +) k = crypt_activate_by_keyfile(cd, argv[2], CRYPT_ANY_SLOT, key_file, keyfile_size, flags); else { char **p; @@ -462,8 +495,43 @@ if (pass_volume_key) k = crypt_activate_by_volume_key(cd, argv[2], *p, opt_key_size, flags); - else - k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, *p, strlen(*p), flags); + else { +#if HAVE_GPGME + if (opt_gpg) { + char* buffer = NULL; + size_t length; + gpgme_error_t error; + gpgme_data_t ciphertext; + gpgme_data_t plaintext; + gpgme_ctx_t ctx; + gpgme_check_version(NULL); + if (gpgme_new(&ctx) == GPG_ERR_NO_ERROR) { + gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP); + gpgme_set_passphrase_cb(ctx, passfunc, *p); + if (gpgme_data_new_from_file(&ciphertext, key_file, 1) == GPG_ERR_NO_ERROR) { + if (gpgme_data_new(&plaintext) == GPG_ERR_NO_ERROR) { + if (gpgme_op_decrypt(ctx, ciphertext, plaintext) == GPG_ERR_NO_ERROR) { + buffer = gpgme_data_release_and_get_mem(plaintext, &length); + k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, buffer, length, flags); + gpgme_free(buffer); + } else { + k = -EPERM; + } + } + gpgme_data_release(ciphertext); + } else { + k = -ENOENT; + log_error("Failed to access file: %s", key_file); + } + gpgme_release(ctx); + } else { + k = -EACCES; + log_error("Failed to create gpgme context"); + } + } else +#endif + k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, *p, strlen(*p), flags); + } if (k >= 0) break;