mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-27 13:57:26 +03:00
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.
This commit is contained in:
parent
d3d49e7649
commit
23769fb371
@ -2227,8 +2227,10 @@ executable(
|
|||||||
|
|
||||||
if conf.get('HAVE_LIBCRYPTSETUP') == 1
|
if conf.get('HAVE_LIBCRYPTSETUP') == 1
|
||||||
systemd_cryptsetup_sources = files('''
|
systemd_cryptsetup_sources = files('''
|
||||||
src/cryptsetup/cryptsetup.c
|
|
||||||
src/cryptsetup/cryptsetup-pkcs11.h
|
src/cryptsetup/cryptsetup-pkcs11.h
|
||||||
|
src/cryptsetup/cryptsetup-util.c
|
||||||
|
src/cryptsetup/cryptsetup-util.h
|
||||||
|
src/cryptsetup/cryptsetup.c
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
if conf.get('HAVE_P11KIT') == 1
|
if conf.get('HAVE_P11KIT') == 1
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "ask-password-api.h"
|
#include "ask-password-api.h"
|
||||||
#include "cryptsetup-pkcs11.h"
|
#include "cryptsetup-pkcs11.h"
|
||||||
|
#include "cryptsetup-util.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
@ -19,73 +20,6 @@
|
|||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "strv.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 {
|
struct pkcs11_callback_data {
|
||||||
const char *friendly_name;
|
const char *friendly_name;
|
||||||
usec_t until;
|
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" */
|
/* 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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
110
src/cryptsetup/cryptsetup-util.c
Normal file
110
src/cryptsetup/cryptsetup-util.c
Normal file
@ -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;
|
||||||
|
}
|
13
src/cryptsetup/cryptsetup-util.h
Normal file
13
src/cryptsetup/cryptsetup-util.h
Normal file
@ -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);
|
Loading…
x
Reference in New Issue
Block a user