diff --git a/systemd-204.orig/src/cryptsetup/cryptsetup.c b/systemd-204/src/cryptsetup/cryptsetup.c
index 2f7a68a..61d3ef8 100644
--- a/systemd-204.orig/src/cryptsetup/cryptsetup.c
+++ b/systemd-204/src/cryptsetup/cryptsetup.c
@@ -40,6 +40,7 @@ static unsigned opt_key_size = 0;
 static unsigned opt_keyfile_size = 0;
 static unsigned opt_keyfile_offset = 0;
 static char *opt_hash = NULL;
+static char *opt_keyhandler = NULL;
 static unsigned opt_tries = 0;
 static bool opt_readonly = false;
 static bool opt_verify = false;
@@ -106,6 +107,23 @@ static int parse_one_option(const char *option) {
                 free(opt_hash);
                 opt_hash = t;
 
+        } else if (startswith(option, "keyhandler=")) {
+                char *t;
+
+		if (!option[11] || !path_is_absolute(option+11)) {
+			log_error("keyhandler= path is invalid, ignoring.");
+			free(opt_keyhandler);
+			opt_keyhandler = NULL;
+			return 0;
+		}
+
+                t = strdup(option+11);
+                if (!t)
+                        return -ENOMEM;
+
+                free(opt_keyhandler);
+                opt_keyhandler = t;
+
         } else if (startswith(option, "tries=")) {
 
                 if (safe_atou(option+6, &opt_tries) < 0) {
@@ -292,22 +310,24 @@ int main(int argc, char *argv[]) {
                         goto finish;
                 }
 
-                if (argc >= 5 &&
-                    argv[4][0] &&
-                    !streq(argv[4], "-") &&
-                    !streq(argv[4], "none")) {
+                if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) {
+                        if (parse_options(argv[5]) < 0)
+                                goto finish;
+                }
 
-                        if (!path_is_absolute(argv[4]))
+                if (argc >= 5) {
+                        if (opt_keyhandler)
+                                key_file = argv[4]; /* used as arg to keyscript */
+                        else if (argv[4][0] &&
+                                 !streq(argv[4], "-") &&
+                                 !streq(argv[4], "none"))
+                                /* do nothing */;
+                        else if (!path_is_absolute(argv[4]))
                                 log_error("Password file path %s is not absolute. Ignoring.", argv[4]);
                         else
                                 key_file = argv[4];
                 }
 
-                if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) {
-                        if (parse_options(argv[5]) < 0)
-                                goto finish;
-                }
-
                 /* A delicious drop of snake oil */
                 mlockall(MCL_FUTURE);
 
@@ -390,6 +410,13 @@ int main(int argc, char *argv[]) {
                         strv_free(passwords);
                         passwords = NULL;
 
+			/* We only launch the handler once */
+			if (opt_keyhandler && try == 0) {
+				passwords = strv_new(opt_keyhandler, key_file, NULL);
+				/* We unset the key_file as it is only an argument to our handler and it has been copied above */
+				key_file = NULL;
+			}
+
                         if (!key_file) {
                                 char *text, **p;
 
@@ -497,9 +524,12 @@ int main(int argc, char *argv[]) {
                                  crypt_get_volume_key_size(cd)*8,
                                  argv[3]);
 
-                        if (key_file) {
+                        if (key_file || (opt_keyhandler && try == 0)) {
                                 struct stat st;
 
+				if (opt_keyhandler)
+					key_file = passwords[0];
+
                                 /* Ideally we'd do this on the open
                                  * fd, but since this is just a
                                  * warning it's OK to do this in two
@@ -512,9 +542,18 @@ int main(int argc, char *argv[]) {
                                                 opt_keyfile_offset, flags);
                                 if (k < 0) {
                                         log_error("Failed to activate with key file '%s': %s", key_file, strerror(-k));
+					/* Remove the temporary file created by our agent as it contains our key! */
+					if (opt_keyhandler)
+						unlink(key_file);
                                         key_file = NULL;
                                         continue;
                                 }
+
+				/* Remove the temporary file created by our agent as it contains our key! */
+				if (opt_keyhandler) {
+					unlink(key_file);
+					key_file = NULL;
+				}
                         } else {
                                 char **p;
 
diff --git a/systemd-204.orig/src/shared/ask-password-api.c b/systemd-204/src/shared/ask-password-api.c
index 4557155..36af254 100644
--- a/systemd-204.orig/src/shared/ask-password-api.c
+++ b/systemd-204/src/shared/ask-password-api.c
@@ -372,6 +372,17 @@ int ask_password_agent(
         if (icon)
                 fprintf(f, "Icon=%s\n", icon);
 
+        /* We assume the keyhandler path and options are provided */                                                                                                    
+        if (strv_length(*_passphrases) == 2) {                                                                                                                          
+                char **p = *_passphrases;                                                                                                                               
+                fprintf(f, "KeyHandler=%s\n"                                                                                                                            
+                           "KeyOpts=%s\n",                                                                                                                              
+                           p[0],                                                                                                                                        
+                           p[1]);                                                                                                                                       
+                strv_free(*_passphrases);                                                                                                                               
+                *_passphrases = NULL;                                                                                                                                   
+        }                                                                                                                                                               
+
         fflush(f);
 
         if (ferror(f)) {
diff --git a/systemd-204.orig/src/tty-ask-password-agent/tty-ask-password-agent.c b/systemd-204/src/tty-ask-password-agent/tty-ask-password-agent.c
index f463662..a8e399a 100644
--- a/systemd-204.orig/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/systemd-204/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -246,7 +246,7 @@ finish:
 }
 
 static int parse_password(const char *filename, char **wall) {
-        char *socket_name = NULL, *message = NULL, *packet = NULL;
+        char *socket_name = NULL, *message = NULL, *packet = NULL, *keyhandler = NULL, *keyopts = NULL;
         uint64_t not_after = 0;
         unsigned pid = 0;
         int socket_fd = -1;
@@ -258,6 +258,8 @@ static int parse_password(const char *filename, char **wall) {
                 { "Ask", "Message",      config_parse_string,   0, &message       },
                 { "Ask", "PID",          config_parse_unsigned, 0, &pid           },
                 { "Ask", "AcceptCached", config_parse_bool,     0, &accept_cached },
+		{ "Ask", "KeyHandler",   config_parse_string,   0, &keyhandler    },
+		{ "Ask", "KeyOpts",      config_parse_string,   0, &keyopts       },
                 { NULL, NULL, NULL, 0, NULL }
         };
 
@@ -338,7 +340,59 @@ static int parse_password(const char *filename, char **wall) {
                         goto finish;
                 }
 
-                if (arg_plymouth) {
+                if (keyhandler) {
+                        char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
+                        int fd = -1;
+                        pid_t pid;
+
+                        fd = mkostemp(temp, O_WRONLY|O_CLOEXEC);
+                        if (fd < 0) {
+                                log_error("Failed to create password file: %m");
+                                r = -errno;
+                                goto finish;
+                        }
+
+                        fchmod(fd, 0644);
+
+                        pid = fork();
+
+                        if (pid < 0) {
+                                log_error("Failed to fork: %m");
+                                r = -errno;
+                                close_nointr_nofail(fd);
+                                goto finish;
+                        } else if (pid > 0) {
+                                close_nointr_nofail(fd);
+                                waitpid(pid, NULL, 0);
+                                
+                                /* send back the temporary filename that now contains our key */
+                                packet_length = 2 + strlen(temp);
+
+                                if (!(packet = new(char, packet_length)))
+                                        r = -ENOMEM;
+                                else {
+                                        char *d;
+                                        packet[0] = '+';
+                                        d = packet+1;
+                                        d = stpcpy(d, temp) + 1;
+                                }
+                        } else if (pid == 0) {
+                                /* launch the keyhandler program and redirect its output to our temporary file */
+                                const char *args[3];
+
+                                if (dup2(fd, STDOUT_FILENO) < 0)
+                                        _exit(EXIT_FAILURE);
+
+                                close(fd);
+
+                                args[0] = keyhandler;
+                                args[1] = keyopts;
+                                args[2] = NULL;
+
+                                execv(args[0], (char **)args);
+                                _exit(EXIT_FAILURE);
+                        }
+                } else if (arg_plymouth) {
                         _cleanup_strv_free_ char **passwords = NULL;
 
                         if ((r = ask_password_plymouth(message, not_after, filename, accept_cached, &passwords)) >= 0) {
