/*
- * util_crypt - cipher utilities for cryptsetup
+ * utils_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
- * Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
return 0;
}
+ /* Short version for "empty" cipher */
+ if (!strcmp(s, "null")) {
+ strncpy(cipher, "cipher_null", MAX_CIPHER_LEN);
+ strncpy(cipher_mode, "ecb", 9);
+ if (key_nums)
+ *key_nums = 0;
+ return 0;
+ }
+
if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]", cipher) == 1) {
strncpy(cipher_mode, "cbc-plain", 10);
if (key_nums)
*/
int crypt_get_key(const char *prompt,
char **key, size_t *key_size,
- size_t keyfile_size_max, const char *key_file,
- int timeout, int verify,
+ size_t keyfile_offset, size_t keyfile_size_max,
+ const char *key_file, int timeout, int verify,
struct crypt_device *cd)
{
int fd, regular_file, read_stdin, char_read, unlimited_read = 0;
int r = -EINVAL;
- char *pass = NULL;
- size_t buflen, i;
+ char *pass = NULL, tmp;
+ size_t buflen, i, file_read_size;
struct stat st;
*key = NULL;
/* Passphrase read from stdin? */
read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
- if (read_stdin && isatty(STDIN_FILENO))
+ if (read_stdin && isatty(STDIN_FILENO)) {
+ if (keyfile_offset) {
+ log_err(cd, _("Cannot use offset with terminal input.\n"));
+ return -EINVAL;
+ }
return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd);
+ }
if (read_stdin)
log_dbg("STDIN descriptor passphrase entry requested.");
}
if(S_ISREG(st.st_mode)) {
regular_file = 1;
+ file_read_size = (size_t)st.st_size;
+
+ if (keyfile_offset > file_read_size) {
+ log_err(cd, _("Cannot seek to requested keyfile offset.\n"));
+ goto out_err;
+ }
+ file_read_size -= keyfile_offset;
+
/* known keyfile size, alloc it in one step */
- if ((size_t)st.st_size >= keyfile_size_max)
+ if (file_read_size >= keyfile_size_max)
buflen = keyfile_size_max;
- else if (st.st_size)
- buflen = st.st_size;
+ else if (file_read_size)
+ buflen = file_read_size;
}
}
goto out_err;
}
+ /* Discard keyfile_offset bytes on input */
+ for(i = 0; i < keyfile_offset; i++)
+ if (read(fd, &tmp, 1) != 1) {
+ log_err(cd, _("Cannot seek to requested keyfile offset.\n"));
+ goto out_err;
+ }
+
for(i = 0; i < keyfile_size_max; i++) {
if(i == buflen) {
buflen += 4096;
/* Fail if we exceeded internal default (no specified size) */
if (unlimited_read && i == keyfile_size_max) {
- log_err(cd, _("Maximum keyfile size exceeeded.\n"));
+ log_err(cd, _("Maximum keyfile size exceeded.\n"));
goto out_err;
}
crypt_safe_free(pass);
return r;
}
+
+ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
+{
+ char buf[3] = "xx\0", *endp, *bytes;
+ size_t i, len;
+
+ len = strlen(hex);
+ if (len % 2)
+ return -EINVAL;
+ len /= 2;
+
+ bytes = safe_alloc ? crypt_safe_alloc(len) : malloc(len);
+ if (!bytes)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ memcpy(buf, &hex[i * 2], 2);
+ bytes[i] = strtoul(buf, &endp, 16);
+ if (endp != &buf[2]) {
+ safe_alloc ? crypt_safe_free(bytes) : free(bytes);
+ return -EINVAL;
+ }
+ }
+ *result = bytes;
+ return i;
+}