#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096
-#define MAX_TTY_PASSWORD_LEN 512
-
/* private struct crypt_options flags */
#define CRYPT_FLAG_FREE_DEVICE (1 << 24)
int get_device_infos(const char *device, struct device_infos *infos, struct crypt_device *cd);
int wipe_device_header(const char *device, int sectors);
-void get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
- const char *key_file, int timeout, int how2verify,
- struct crypt_device *cd);
-
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
static int verify_other_keyslot(struct crypt_device *cd,
const char *key_file,
- unsigned int flags,
int keyIndex)
{
struct volume_key *vk;
char *password = NULL;
unsigned int passwordLen;
- get_key(_("Enter any remaining LUKS passphrase: "), &password,
- &passwordLen, 0, key_file, cd->timeout, flags, cd);
+ crypt_get_key(_("Enter any remaining LUKS passphrase: "), &password,
+ &passwordLen, 0, key_file, cd->timeout, cd->password_verify, cd);
if(!password)
return -EINVAL;
static int find_keyslot_by_passphrase(struct crypt_device *cd,
const char *key_file,
- unsigned int flags,
char *message)
{
struct volume_key *vk;
unsigned int passwordLen;
int keyIndex;
- get_key(message,&password,&passwordLen, 0, key_file,
- cd->timeout, flags, cd);
+ crypt_get_key(message,&password,&passwordLen, 0, key_file,
+ cd->timeout, cd->password_verify, cd);
if(!password)
return -EINVAL;
int r = -EINVAL;
if (key_slot == CRYPT_ANY_SLOT) {
- key_slot = find_keyslot_by_passphrase(cd, key_file, 0,
+ key_slot = find_keyslot_by_passphrase(cd, key_file,
_("Enter LUKS passphrase to be deleted: "));
if(key_slot < 0) {
r = -EPERM;
goto out;
}
- log_std(cd, _("key slot %d selected for deletion.\n"), key_slot);
+ log_std(cd, _("Key slot %d selected for deletion.\n"), key_slot);
}
ki = crypt_keyslot_status(cd, key_slot);
}
if(verify)
- r = verify_other_keyslot(cd, other_key_file, 0, key_slot);
+ r = verify_other_keyslot(cd, other_key_file, key_slot);
else
r = 0;
static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
unsigned int *key_len, int force_verify)
{
- int r, flags = 0;
+ int r;
if (cd->password) {
*key = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
*key = NULL;
} else
*key_len = r;
- } else {
- if (force_verify || cd->password_verify)
- flags |= CRYPT_FLAG_VERIFY_IF_POSSIBLE;
- get_key(msg, key, key_len, 0, NULL, cd->timeout, flags, cd);
- }
+ } else
+ crypt_get_key(msg, key, key_len, 0, NULL, cd->timeout,
+ (force_verify || cd->password_verify), cd);
}
static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot,
char **key, unsigned int *key_len,
const char *key_file, size_t key_size)
{
- get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
+ crypt_get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
}
static int _crypt_init(struct crypt_device **cd,
if (r)
return r;
- get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
- options->key_file, cd->timeout, options->flags, cd);
+ crypt_get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
+ options->key_file, cd->timeout, cd->password_verify, cd);
if (!key)
r = -ENOENT;
else
goto out;
}
- get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
- options->new_key_file, options->timeout, options->flags, cd);
+ crypt_get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
+ options->new_key_file, cd->timeout, cd->password_verify, cd);
if(!password) {
r = -EINVAL;
return write_blockwise(fd, buf, count) + innerCount;
}
-/* Password reading helpers */
-
-static int untimed_read(int fd, char *pass, size_t maxlen)
-{
- ssize_t i;
-
- i = read(fd, pass, maxlen);
- if (i > 0) {
- pass[i-1] = '\0';
- i = 0;
- } else if (i == 0) { /* EOF */
- *pass = 0;
- i = -1;
- }
- return i;
-}
-
-static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
-{
- struct timeval t;
- fd_set fds;
- int failed = -1;
-
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- t.tv_sec = timeout;
- t.tv_usec = 0;
-
- if (select(fd+1, &fds, NULL, NULL, &t) > 0)
- failed = untimed_read(fd, pass, maxlen);
-
- return failed;
-}
-
-static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
- long timeout)
-{
- struct termios orig, tmp;
- int failed = -1;
- int infd = STDIN_FILENO, outfd;
-
- if (maxlen < 1)
- goto out_err;
-
- /* Read and write to /dev/tty if available */
- if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
- infd = STDIN_FILENO;
- outfd = STDERR_FILENO;
- }
-
- if (tcgetattr(infd, &orig))
- goto out_err;
-
- memcpy(&tmp, &orig, sizeof(tmp));
- tmp.c_lflag &= ~ECHO;
-
- if (write(outfd, prompt, strlen(prompt)) < 0)
- goto out_err;
-
- tcsetattr(infd, TCSAFLUSH, &tmp);
- if (timeout)
- failed = timed_read(infd, pass, maxlen, timeout);
- else
- failed = untimed_read(infd, pass, maxlen);
- tcsetattr(infd, TCSAFLUSH, &orig);
-
-out_err:
- if (!failed && write(outfd, "\n", 1));
-
- if (infd != STDIN_FILENO)
- close(infd);
- return failed;
-}
-
-/*
- * Password reading behaviour matrix of get_key
- * FIXME: rewrite this from scratch.
- * p v n h
- * -----------------+---+---+---+---
- * interactive | Y | Y | Y | Inf
- * from fd | N | N | Y | Inf
- * from binary file | N | N | N | Inf or options->key_size
- *
- * Legend: p..prompt, v..can verify, n..newline-stop, h..read horizon
- *
- * Note: --key-file=- is interpreted as a read from a binary file (stdin)
- */
-
-void get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
- const char *key_file, int timeout, int how2verify,
- struct crypt_device *cd)
-{
- int fd = -1;
- const int verify = how2verify & CRYPT_FLAG_VERIFY;
- const int verify_if_possible = how2verify & CRYPT_FLAG_VERIFY_IF_POSSIBLE;
- char *pass = NULL;
- int read_horizon;
- int regular_file = 0;
- int read_stdin;
- int r;
- struct stat st;
-
- /* Passphrase read from stdin? */
- read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
-
- /* read_horizon applies only for real keyfile, not stdin or terminal */
- read_horizon = (key_file && !read_stdin) ? key_size : 0 /* until EOF */;
-
- /* Setup file descriptior */
- fd = read_stdin ? STDIN_FILENO : open(key_file, O_RDONLY);
- if (fd < 0) {
- log_err(cd, _("Failed to open key file %s.\n"), key_file ?: "-");
- goto out_err;
- }
-
- /* Interactive case */
- if(isatty(fd)) {
- int i;
-
- pass = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
- if (!pass || (i = interactive_pass(prompt, pass, MAX_TTY_PASSWORD_LEN, timeout))) {
- log_err(cd, _("Error reading passphrase from terminal.\n"));
- goto out_err;
- }
- if (verify || verify_if_possible) {
- char pass_verify[MAX_TTY_PASSWORD_LEN];
- i = interactive_pass(_("Verify passphrase: "), pass_verify, sizeof(pass_verify), timeout);
- if (i || strcmp(pass, pass_verify) != 0) {
- log_err(cd, _("Passphrases do not match.\n"));
- goto out_err;
- }
- memset(pass_verify, 0, sizeof(pass_verify));
- }
- *passLen = strlen(pass);
- *key = pass;
- } else {
- /*
- * This is either a fd-input or a file, in neither case we can verify the input,
- * however we don't stop on new lines if it's a binary file.
- */
- int buflen, i;
-
- if(verify) {
- log_err(cd, _("Can't do passphrase verification on non-tty inputs.\n"));
- goto out_err;
- }
- /* The following for control loop does an exhausting
- * read on the key material file, if requested with
- * key_size == 0, as it's done by LUKS. However, we
- * should warn the user, if it's a non-regular file,
- * such as /dev/random, because in this case, the loop
- * will read forever.
- */
- if(!read_stdin && read_horizon == 0) {
- if(stat(key_file, &st) < 0) {
- log_err(cd, _("Failed to stat key file %s.\n"), key_file);
- goto out_err;
- }
- if(!S_ISREG(st.st_mode))
- log_std(cd, _("Warning: exhausting read requested, but key file %s"
- " is not a regular file, function might never return.\n"),
- key_file);
- else
- regular_file = 1;
- }
- buflen = 0;
- for(i = 0; read_horizon == 0 || i < read_horizon; i++) {
- if(i >= buflen - 1) {
- buflen += 128;
- pass = crypt_safe_realloc(pass, buflen);
- if (!pass) {
- log_err(cd, _("Out of memory while reading passphrase.\n"));
- goto out_err;
- }
- }
-
- r = read(fd, pass + i, 1);
- if (r < 0) {
- log_err(cd, _("Error reading passphrase.\n"));
- goto out_err;
- }
-
- /* Stop on newline only if not requested read from keyfile */
- if(r == 0 || (!key_file && pass[i] == '\n'))
- break;
- }
- /* Fail if piped input dies reading nothing */
- if(!i && !regular_file) {
- log_dbg("Error reading passphrase.");
- goto out_err;
- }
- pass[i] = 0;
- *key = pass;
- *passLen = i;
- }
- if(fd != STDIN_FILENO)
- close(fd);
- return;
-
-out_err:
- if(fd >= 0 && fd != STDIN_FILENO)
- close(fd);
- if(pass)
- crypt_safe_free(pass);
- *key = NULL;
- *passLen = 0;
-}
-
int device_ready(struct crypt_device *cd, const char *device, int mode)
{
int devfd, r = 1;
crypt_safe_free(data);
return new_data;
}
+
+/* Password reading helpers */
+static int untimed_read(int fd, char *pass, size_t maxlen)
+{
+ ssize_t i;
+
+ i = read(fd, pass, maxlen);
+ if (i > 0) {
+ pass[i-1] = '\0';
+ i = 0;
+ } else if (i == 0) { /* EOF */
+ *pass = 0;
+ i = -1;
+ }
+ return i;
+}
+
+static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
+{
+ struct timeval t;
+ fd_set fds;
+ int failed = -1;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ t.tv_sec = timeout;
+ t.tv_usec = 0;
+
+ if (select(fd+1, &fds, NULL, NULL, &t) > 0)
+ failed = untimed_read(fd, pass, maxlen);
+
+ return failed;
+}
+
+static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
+ long timeout)
+{
+ struct termios orig, tmp;
+ int failed = -1;
+ int infd = STDIN_FILENO, outfd;
+
+ if (maxlen < 1)
+ goto out_err;
+
+ /* Read and write to /dev/tty if available */
+ if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
+ infd = STDIN_FILENO;
+ outfd = STDERR_FILENO;
+ }
+
+ if (tcgetattr(infd, &orig))
+ goto out_err;
+
+ memcpy(&tmp, &orig, sizeof(tmp));
+ tmp.c_lflag &= ~ECHO;
+
+ if (write(outfd, prompt, strlen(prompt)) < 0)
+ goto out_err;
+
+ tcsetattr(infd, TCSAFLUSH, &tmp);
+ if (timeout)
+ failed = timed_read(infd, pass, maxlen, timeout);
+ else
+ failed = untimed_read(infd, pass, maxlen);
+ tcsetattr(infd, TCSAFLUSH, &orig);
+
+out_err:
+ if (!failed && write(outfd, "\n", 1));
+
+ if (infd != STDIN_FILENO)
+ close(infd);
+ return failed;
+}
+
+/*
+ * Password reading behaviour matrix of get_key
+ * FIXME: rewrite this from scratch.
+ * p v n h
+ * -----------------+---+---+---+---
+ * interactive | Y | Y | Y | Inf
+ * from fd | N | N | Y | Inf
+ * from binary file | N | N | N | Inf or options->key_size
+ *
+ * Legend: p..prompt, v..can verify, n..newline-stop, h..read horizon
+ *
+ * Note: --key-file=- is interpreted as a read from a binary file (stdin)
+ */
+
+void crypt_get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
+ const char *key_file, int timeout, int verify,
+ struct crypt_device *cd)
+{
+ int fd = -1;
+ char *pass = NULL;
+ int read_horizon;
+ int regular_file = 0;
+ int read_stdin;
+ int r;
+ struct stat st;
+
+ /* Passphrase read from stdin? */
+ read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
+
+ /* read_horizon applies only for real keyfile, not stdin or terminal */
+ read_horizon = (key_file && !read_stdin) ? key_size : 0 /* until EOF */;
+
+ /* Setup file descriptior */
+ fd = read_stdin ? STDIN_FILENO : open(key_file, O_RDONLY);
+ if (fd < 0) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Failed to open key file.\n"));
+ goto out_err;
+ }
+
+ /* Interactive case */
+ if(isatty(fd)) {
+ int i;
+
+ pass = crypt_safe_alloc(MAX_TTY_PASSWORD_LEN);
+ if (!pass || (i = interactive_pass(prompt, pass, MAX_TTY_PASSWORD_LEN, timeout))) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Error reading passphrase from terminal.\n"));
+ goto out_err;
+ }
+ if (verify) {
+ char pass_verify[MAX_TTY_PASSWORD_LEN];
+ i = interactive_pass(_("Verify passphrase: "), pass_verify, sizeof(pass_verify), timeout);
+ if (i || strcmp(pass, pass_verify) != 0) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Passphrases do not match.\n"));
+ goto out_err;
+ }
+ memset(pass_verify, 0, sizeof(pass_verify));
+ }
+ *passLen = strlen(pass);
+ *key = pass;
+ } else {
+ /*
+ * This is either a fd-input or a file, in neither case we can verify the input,
+ * however we don't stop on new lines if it's a binary file.
+ */
+ int buflen, i;
+
+ /* The following for control loop does an exhausting
+ * read on the key material file, if requested with
+ * key_size == 0, as it's done by LUKS. However, we
+ * should warn the user, if it's a non-regular file,
+ * such as /dev/random, because in this case, the loop
+ * will read forever.
+ */
+ if(!read_stdin && read_horizon == 0) {
+ if(stat(key_file, &st) < 0) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Failed to stat key file.\n"));
+ goto out_err;
+ }
+ if(!S_ISREG(st.st_mode))
+ crypt_log(cd, CRYPT_LOG_NORMAL,
+ _("Warning: exhausting read requested, but key file"
+ " is not a regular file, function might never return.\n"));
+ else
+ regular_file = 1;
+ }
+ buflen = 0;
+ for(i = 0; read_horizon == 0 || i < read_horizon; i++) {
+ if(i >= buflen - 1) {
+ buflen += 128;
+ pass = crypt_safe_realloc(pass, buflen);
+ if (!pass) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Out of memory while reading passphrase.\n"));
+ goto out_err;
+ }
+ }
+
+ r = read(fd, pass + i, 1);
+ if (r < 0) {
+ crypt_log(cd, CRYPT_LOG_ERROR,
+ _("Error reading passphrase.\n"));
+ goto out_err;
+ }
+
+ /* Stop on newline only if not requested read from keyfile */
+ if(r == 0 || (!key_file && pass[i] == '\n'))
+ break;
+ }
+ /* Fail if piped input dies reading nothing */
+ if(!i && !regular_file)
+ goto out_err;
+ pass[i] = 0;
+ *key = pass;
+ *passLen = i;
+ }
+ if(fd != STDIN_FILENO)
+ close(fd);
+ return;
+
+out_err:
+ if(fd >= 0 && fd != STDIN_FILENO)
+ close(fd);
+ if(pass)
+ crypt_safe_free(pass);
+ *key = NULL;
+ *passLen = 0;
+}
#define MAX_CIPHER_LEN 32
#define MAX_CIPHER_LEN_STR "32"
+#define MAX_TTY_PASSWORD_LEN 512
+
+struct crypt_device;
+
int crypt_parse_name_and_mode(const char *s, char *cipher, char *cipher_mode);
+void crypt_get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
+ const char *key_file, int timeout, int how2verify,
+ struct crypt_device *cd);
+
void *crypt_safe_alloc(size_t size);
void crypt_safe_free(void *data);
void *crypt_safe_realloc(void *data, size_t size);