summaryrefslogtreecommitdiff
path: root/src/cryptsetup
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-04-29 14:50:38 +0200
committerLennart Poettering <lennart@poettering.net>2020-05-19 17:28:16 +0200
commit23769fb3711e268386453ae3b4d8ed3feadeb516 (patch)
treedd8eee78b421363155bffcb3bfefb3702c4a6238 /src/cryptsetup
parentd3d49e76498572940f5a691848b9df2f86b86d78 (diff)
downloadsystemd-23769fb3711e268386453ae3b4d8ed3feadeb516.tar.gz
cryptsetup: split out key loading from pkcs11 code and teach search path logic
Let's do some rearrangements, so that we can later on use this to automatically search for a key file.
Diffstat (limited to 'src/cryptsetup')
-rw-r--r--src/cryptsetup/cryptsetup-pkcs11.c70
-rw-r--r--src/cryptsetup/cryptsetup-util.c110
-rw-r--r--src/cryptsetup/cryptsetup-util.h13
3 files changed, 125 insertions, 68 deletions
diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c
index ec9186a6aa..97a8c68ee8 100644
--- a/src/cryptsetup/cryptsetup-pkcs11.c
+++ b/src/cryptsetup/cryptsetup-pkcs11.c
@@ -10,6 +10,7 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "cryptsetup-pkcs11.h"
+#include "cryptsetup-util.h"
#include "escape.h"
#include "fd-util.h"
#include "format-util.h"
@@ -19,73 +20,6 @@
#include "stat-util.h"
#include "strv.h"
-#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
-
-static int load_key_file(
- const char *key_file,
- size_t key_file_size,
- uint64_t key_file_offset,
- void **ret_encrypted_key,
- size_t *ret_encrypted_key_size) {
-
- _cleanup_(erase_and_freep) char *buffer = NULL;
- _cleanup_close_ int fd = -1;
- ssize_t n;
- int r;
-
- assert(key_file);
- assert(ret_encrypted_key);
- assert(ret_encrypted_key_size);
-
- fd = open(key_file, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return log_error_errno(errno, "Failed to load encrypted PKCS#11 key: %m");
-
- if (key_file_size == 0) {
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- return log_error_errno(errno, "Failed to stat key file: %m");
-
- r = stat_verify_regular(&st);
- if (r < 0)
- return log_error_errno(r, "Key file is not a regular file: %m");
-
- if (st.st_size == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
- if ((uint64_t) st.st_size > KEY_FILE_SIZE_MAX) {
- char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
- return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
- "Key file larger (%s) than allowed maximum size (%s), refusing.",
- format_bytes(buf1, sizeof(buf1), st.st_size),
- format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
- }
-
- if (key_file_offset >= (uint64_t) st.st_size)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
-
- key_file_size = st.st_size - key_file_offset;
- }
-
- buffer = malloc(key_file_size);
- if (!buffer)
- return log_oom();
-
- if (key_file_offset > 0)
- n = pread(fd, buffer, key_file_size, key_file_offset);
- else
- n = read(fd, buffer, key_file_size);
- if (n < 0)
- return log_error_errno(errno, "Failed to read PKCS#11 key file: %m");
- if (n == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
-
- *ret_encrypted_key = TAKE_PTR(buffer);
- *ret_encrypted_key_size = (size_t) n;
-
- return 0;
-}
-
struct pkcs11_callback_data {
const char *friendly_name;
usec_t until;
@@ -181,7 +115,7 @@ int decrypt_pkcs11_key(
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
- r = load_key_file(key_file, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
+ r = load_key_file(key_file, NULL, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
if (r < 0)
return r;
diff --git a/src/cryptsetup/cryptsetup-util.c b/src/cryptsetup/cryptsetup-util.c
new file mode 100644
index 0000000000..8ae70a5d10
--- /dev/null
+++ b/src/cryptsetup/cryptsetup-util.c
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "cryptsetup-util.h"
+#include "fd-util.h"
+#include "format-util.h"
+#include "memory-util.h"
+#include "path-util.h"
+#include "stat-util.h"
+#include "strv.h"
+
+#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
+
+int load_key_file(
+ const char *key_file,
+ char **search_path,
+ size_t key_file_size,
+ uint64_t key_file_offset,
+ void **ret_key,
+ size_t *ret_key_size) {
+
+ _cleanup_(erase_and_freep) char *buffer = NULL;
+ _cleanup_free_ char *discovered_path = NULL;
+ _cleanup_close_ int fd = -1;
+ ssize_t n;
+ int r;
+
+ assert(key_file);
+ assert(ret_key);
+ assert(ret_key_size);
+
+ if (strv_isempty(search_path) || path_is_absolute(key_file)) {
+ fd = open(key_file, O_RDONLY|O_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to load key file '%s': %m", key_file);
+ } else {
+ char **i;
+
+ STRV_FOREACH(i, search_path) {
+ _cleanup_free_ char *joined;
+
+ joined = path_join(*i, key_file);
+ if (!joined)
+ return log_oom();
+
+ fd = open(joined, O_RDONLY|O_CLOEXEC);
+ if (fd >= 0) {
+ discovered_path = TAKE_PTR(joined);
+ break;
+ }
+ if (errno != ENOENT)
+ return log_error_errno(errno, "Failed to load key file '%s': %m", joined);
+ }
+
+ if (!discovered_path) {
+ /* Search path supplied, but file not found, report by returning NULL, but not failing */
+ *ret_key = NULL;
+ *ret_key_size = 0;
+ return 0;
+ }
+
+ assert(fd >= 0);
+ key_file = discovered_path;
+ }
+
+ if (key_file_size == 0) {
+ struct stat st;
+
+ if (fstat(fd, &st) < 0)
+ return log_error_errno(errno, "Failed to stat key file '%s': %m", key_file);
+
+ r = stat_verify_regular(&st);
+ if (r < 0)
+ return log_error_errno(r, "Key file is not a regular file: %m");
+
+ if (st.st_size == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
+ if ((uint64_t) st.st_size > KEY_FILE_SIZE_MAX) {
+ char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
+ return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
+ "Key file larger (%s) than allowed maximum size (%s), refusing.",
+ format_bytes(buf1, sizeof(buf1), st.st_size),
+ format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
+ }
+
+ if (key_file_offset >= (uint64_t) st.st_size)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
+
+ key_file_size = st.st_size - key_file_offset;
+ }
+
+ buffer = malloc(key_file_size);
+ if (!buffer)
+ return log_oom();
+
+ if (key_file_offset > 0)
+ n = pread(fd, buffer, key_file_size, key_file_offset);
+ else
+ n = read(fd, buffer, key_file_size);
+ if (n < 0)
+ return log_error_errno(errno, "Failed to read key file '%s': %m", key_file);
+ if (n == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
+
+ *ret_key = TAKE_PTR(buffer);
+ *ret_key_size = (size_t) n;
+
+ return 1;
+}
diff --git a/src/cryptsetup/cryptsetup-util.h b/src/cryptsetup/cryptsetup-util.h
new file mode 100644
index 0000000000..7bb78227dc
--- /dev/null
+++ b/src/cryptsetup/cryptsetup-util.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+int load_key_file(
+ const char *key_file,
+ char **search_path,
+ size_t key_file_size,
+ uint64_t key_file_offset,
+ void **ret_key,
+ size_t *ret_key_size);