+ assert(strv_length(passwords2) == 1);
+
+ if (!streq(*passwords[0], passwords2[0])) {
+ log_warning("Passwords did not match, retrying.");
+ return -EAGAIN;
+ }
+ }
+
+ strv_uniq(*passwords);
+
+ STRV_FOREACH(p, *passwords) {
+ char *c;
+
+ if (strlen(*p)+1 >= opt_key_size)
+ continue;
+
+ /* Pad password if necessary */
+ if (!(c = new(char, opt_key_size)))
+ return log_oom();
+
+ strncpy(c, *p, opt_key_size);
+ free(*p);
+ *p = c;
+ }
+
+ return 0;
+}
+
+static int attach_tcrypt(struct crypt_device *cd,
+ const char *name,
+ const char *key_file,
+ char **passwords,
+ uint32_t flags) {
+ int r = 0;
+ _cleanup_free_ char *passphrase = NULL;
+ struct crypt_params_tcrypt params = {
+ .flags = CRYPT_TCRYPT_LEGACY_MODES,
+ .keyfiles = (const char **)opt_tcrypt_keyfiles,
+ .keyfiles_count = strv_length(opt_tcrypt_keyfiles)
+ };
+
+ assert(cd);
+ assert(name);
+ assert(key_file || passwords);
+
+ if (opt_tcrypt_hidden)
+ params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
+
+ if (opt_tcrypt_system)
+ params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
+
+ if (key_file) {
+ r = read_one_line_file(key_file, &passphrase);
+ if (r < 0) {
+ log_error("Failed to read password file '%s': %s", key_file, strerror(-r));
+ return -EAGAIN;
+ }
+
+ params.passphrase = passphrase;
+ } else
+ params.passphrase = passwords[0];
+ params.passphrase_size = strlen(params.passphrase);
+
+ r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ if (r < 0) {
+ if (key_file && r == -EPERM) {
+ log_error("Failed to activate using password file '%s'.", key_file);
+ return -EAGAIN;
+ }
+ return r;
+ }
+
+ return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);;
+}
+
+static int attach_luks_or_plain(struct crypt_device *cd,
+ const char *name,
+ const char *key_file,
+ char **passwords,
+ uint32_t flags) {
+ int r = 0;
+ bool pass_volume_key = false;
+
+ assert(cd);
+ assert(name);
+ assert(key_file || passwords);
+
+ if (!opt_type || streq(opt_type, CRYPT_LUKS1))
+ r = crypt_load(cd, CRYPT_LUKS1, NULL);
+
+ if ((!opt_type && r < 0) || streq_ptr(opt_type, CRYPT_PLAIN)) {
+ struct crypt_params_plain params = {};
+ const char *cipher, *cipher_mode;
+ _cleanup_free_ char *truncated_cipher = NULL;
+
+ if (opt_hash) {
+ /* plain isn't a real hash type. it just means "use no hash" */
+ if (!streq(opt_hash, "plain"))
+ params.hash = opt_hash;
+ } else
+ params.hash = "ripemd160";
+
+ if (opt_cipher) {
+ size_t l;
+
+ l = strcspn(opt_cipher, "-");
+ truncated_cipher = strndup(opt_cipher, l);
+ if (!truncated_cipher)
+ return log_oom();
+
+ cipher = truncated_cipher;
+ cipher_mode = opt_cipher[l] ? opt_cipher+l+1 : "plain";
+ } else {
+ cipher = "aes";
+ cipher_mode = "cbc-essiv:sha256";
+ }