1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "cryptsetup-util.h"
5 #include "dlfcn-util.h"
7 #include "parse-util.h"
10 static void *cryptsetup_dl
= NULL
;
12 DLSYM_FUNCTION(crypt_activate_by_passphrase
);
13 #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
14 DLSYM_FUNCTION(crypt_activate_by_signed_key
);
16 DLSYM_FUNCTION(crypt_activate_by_volume_key
);
17 DLSYM_FUNCTION(crypt_deactivate_by_name
);
18 DLSYM_FUNCTION(crypt_format
);
19 DLSYM_FUNCTION(crypt_free
);
20 DLSYM_FUNCTION(crypt_get_cipher
);
21 DLSYM_FUNCTION(crypt_get_cipher_mode
);
22 DLSYM_FUNCTION(crypt_get_data_offset
);
23 DLSYM_FUNCTION(crypt_get_device_name
);
24 DLSYM_FUNCTION(crypt_get_dir
);
25 DLSYM_FUNCTION(crypt_get_type
);
26 DLSYM_FUNCTION(crypt_get_uuid
);
27 DLSYM_FUNCTION(crypt_get_verity_info
);
28 DLSYM_FUNCTION(crypt_get_volume_key_size
);
29 DLSYM_FUNCTION(crypt_init
);
30 DLSYM_FUNCTION(crypt_init_by_name
);
31 DLSYM_FUNCTION(crypt_keyslot_add_by_volume_key
);
32 DLSYM_FUNCTION(crypt_keyslot_destroy
);
33 DLSYM_FUNCTION(crypt_keyslot_max
);
34 DLSYM_FUNCTION(crypt_load
);
35 DLSYM_FUNCTION(crypt_resize
);
36 #if HAVE_CRYPT_RESUME_BY_VOLUME_KEY
37 DLSYM_FUNCTION(crypt_resume_by_volume_key
);
39 DLSYM_FUNCTION(crypt_set_data_device
);
40 DLSYM_FUNCTION(crypt_set_debug_level
);
41 DLSYM_FUNCTION(crypt_set_log_callback
);
42 #if HAVE_CRYPT_SET_METADATA_SIZE
43 DLSYM_FUNCTION(crypt_set_metadata_size
);
45 DLSYM_FUNCTION(crypt_set_pbkdf_type
);
46 DLSYM_FUNCTION(crypt_suspend
);
47 DLSYM_FUNCTION(crypt_token_json_get
);
48 DLSYM_FUNCTION(crypt_token_json_set
);
49 #if HAVE_CRYPT_TOKEN_MAX
50 DLSYM_FUNCTION(crypt_token_max
);
52 DLSYM_FUNCTION(crypt_token_status
);
53 DLSYM_FUNCTION(crypt_volume_key_get
);
54 #if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
55 DLSYM_FUNCTION(crypt_reencrypt_init_by_passphrase
);
57 #if HAVE_CRYPT_REENCRYPT
58 DISABLE_WARNING_DEPRECATED_DECLARATIONS
;
59 DLSYM_FUNCTION(crypt_reencrypt
);
62 DLSYM_FUNCTION(crypt_metadata_locking
);
63 #if HAVE_CRYPT_SET_DATA_OFFSET
64 DLSYM_FUNCTION(crypt_set_data_offset
);
66 DLSYM_FUNCTION(crypt_header_restore
);
67 DLSYM_FUNCTION(crypt_volume_key_keyring
);
69 /* Unfortunately libcryptsetup provides neither an environment variable to redirect where to look for token
70 * modules, nor does it have an API to change the token lookup path at runtime. The maintainers suggest using
71 * ELF interposition instead (see https://gitlab.com/cryptsetup/cryptsetup/-/issues/846). Hence let's do
72 * that: let's interpose libcryptsetup's crypt_token_external_path() function with our own, that *does*
73 * honour an environment variable where to look for tokens. This is tremendously useful for debugging
74 * libcryptsetup tokens: set the environment variable to your build dir and you can easily test token modules
75 * without jumping through various hoops. */
77 /* Do this only on new enough compilers that actually support the "symver" attribute. Given this is a debug
78 * feature, let's simply not bother on older compilers */
79 #if BUILD_MODE_DEVELOPER && defined(__has_attribute) && __has_attribute(symver)
80 const char *my_crypt_token_external_path(void); /* prototype for our own implementation */
82 /* We use the "symver" attribute to mark this implementation as the default implementation, and drop the
83 * SD_SHARED namespace we by default attach to our symbols via a version script. */
84 __attribute__((symver("crypt_token_external_path@@")))
85 _public_
const char *my_crypt_token_external_path(void) {
88 e
= secure_getenv("SYSTEMD_CRYPTSETUP_TOKEN_PATH");
92 /* Now chain invoke the original implementation. */
94 typeof(crypt_token_external_path
) *func
;
95 func
= (typeof(crypt_token_external_path
)*) dlsym(cryptsetup_dl
, "crypt_token_external_path");
104 static void cryptsetup_log_glue(int level
, const char *msg
, void *usrptr
) {
107 case CRYPT_LOG_NORMAL
:
110 case CRYPT_LOG_ERROR
:
113 case CRYPT_LOG_VERBOSE
:
116 case CRYPT_LOG_DEBUG
:
120 log_error("Unknown libcryptsetup log level: %d", level
);
124 log_full(level
, "%s", msg
);
127 void cryptsetup_enable_logging(struct crypt_device
*cd
) {
128 /* It's OK to call this with a NULL parameter, in which case libcryptsetup will set the default log
131 * Note that this is also called from dlopen_cryptsetup(), which we call here too. Sounds like an
132 * endless loop, but isn't because we break it via the check for 'cryptsetup_dl' early in
133 * dlopen_cryptsetup(). */
135 if (dlopen_cryptsetup() < 0)
136 return; /* If this fails, let's gracefully ignore the issue, this is just debug logging after
137 * all, and if this failed we already generated a debug log message that should help
138 * to track things down. */
140 sym_crypt_set_log_callback(cd
, cryptsetup_log_glue
, NULL
);
141 sym_crypt_set_debug_level(DEBUG_LOGGING
? CRYPT_DEBUG_ALL
: CRYPT_DEBUG_NONE
);
144 int cryptsetup_set_minimal_pbkdf(struct crypt_device
*cd
) {
146 /* With CRYPT_PBKDF_NO_BENCHMARK flag set .time_ms member is ignored
147 * while .iterations must be set at least to recommended minimum value. */
149 static const struct crypt_pbkdf_type minimal_pbkdf
= {
151 .type
= CRYPT_KDF_PBKDF2
,
152 .iterations
= 1000, /* recommended minimum count for pbkdf2
153 * according to NIST SP 800-132, ch. 5.2 */
154 .flags
= CRYPT_PBKDF_NO_BENCHMARK
159 /* Sets a minimal PKBDF in case we already have a high entropy key. */
161 r
= dlopen_cryptsetup();
165 r
= sym_crypt_set_pbkdf_type(cd
, &minimal_pbkdf
);
172 int cryptsetup_get_token_as_json(
173 struct crypt_device
*cd
,
175 const char *verify_type
,
178 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
184 /* Extracts and parses the LUKS2 JSON token data from a LUKS2 device. Optionally verifies the type of
185 * the token. Returns:
187 * -EINVAL → token index out of range or "type" field missing
188 * -ENOENT → token doesn't exist
189 * -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type
192 r
= dlopen_cryptsetup();
196 r
= sym_crypt_token_json_get(cd
, idx
, &text
);
200 r
= json_parse(text
, 0, &v
, NULL
, NULL
);
207 w
= json_variant_by_key(v
, "type");
211 if (!streq_ptr(json_variant_string(w
), verify_type
))
221 int cryptsetup_add_token_json(struct crypt_device
*cd
, JsonVariant
*v
) {
222 _cleanup_free_
char *text
= NULL
;
225 r
= dlopen_cryptsetup();
229 r
= json_variant_format(v
, 0, &text
);
231 return log_debug_errno(r
, "Failed to format token data for LUKS: %m");
233 log_debug("Adding token text <%s>", text
);
235 r
= sym_crypt_token_json_set(cd
, CRYPT_ANY_TOKEN
, text
);
237 return log_debug_errno(r
, "Failed to write token data to LUKS: %m");
243 int dlopen_cryptsetup(void) {
244 #if HAVE_LIBCRYPTSETUP
247 /* libcryptsetup added crypt_reencrypt() in 2.2.0, and marked it obsolete in 2.4.0, replacing it with
248 * crypt_reencrypt_run(), which takes one extra argument but is otherwise identical. The old call is
249 * still available though, and given we want to support 2.2.0 for a while longer, we'll stick to the
250 * old symbol. However, the old symbols now has a GCC deprecation decorator, hence let's turn off
251 * warnings about this for now. */
253 DISABLE_WARNING_DEPRECATED_DECLARATIONS
;
255 r
= dlopen_many_sym_or_warn(
256 &cryptsetup_dl
, "libcryptsetup.so.12", LOG_DEBUG
,
257 DLSYM_ARG(crypt_activate_by_passphrase
),
258 #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
259 DLSYM_ARG(crypt_activate_by_signed_key
),
261 DLSYM_ARG(crypt_activate_by_volume_key
),
262 DLSYM_ARG(crypt_deactivate_by_name
),
263 DLSYM_ARG(crypt_format
),
264 DLSYM_ARG(crypt_free
),
265 DLSYM_ARG(crypt_get_cipher
),
266 DLSYM_ARG(crypt_get_cipher_mode
),
267 DLSYM_ARG(crypt_get_data_offset
),
268 DLSYM_ARG(crypt_get_device_name
),
269 DLSYM_ARG(crypt_get_dir
),
270 DLSYM_ARG(crypt_get_type
),
271 DLSYM_ARG(crypt_get_uuid
),
272 DLSYM_ARG(crypt_get_verity_info
),
273 DLSYM_ARG(crypt_get_volume_key_size
),
274 DLSYM_ARG(crypt_init
),
275 DLSYM_ARG(crypt_init_by_name
),
276 DLSYM_ARG(crypt_keyslot_add_by_volume_key
),
277 DLSYM_ARG(crypt_keyslot_destroy
),
278 DLSYM_ARG(crypt_keyslot_max
),
279 DLSYM_ARG(crypt_load
),
280 DLSYM_ARG(crypt_resize
),
281 #if HAVE_CRYPT_RESUME_BY_VOLUME_KEY
282 DLSYM_ARG(crypt_resume_by_volume_key
),
284 DLSYM_ARG(crypt_set_data_device
),
285 DLSYM_ARG(crypt_set_debug_level
),
286 DLSYM_ARG(crypt_set_log_callback
),
287 #if HAVE_CRYPT_SET_METADATA_SIZE
288 DLSYM_ARG(crypt_set_metadata_size
),
290 DLSYM_ARG(crypt_set_pbkdf_type
),
291 DLSYM_ARG(crypt_suspend
),
292 DLSYM_ARG(crypt_token_json_get
),
293 DLSYM_ARG(crypt_token_json_set
),
294 #if HAVE_CRYPT_TOKEN_MAX
295 DLSYM_ARG(crypt_token_max
),
297 DLSYM_ARG(crypt_token_status
),
298 DLSYM_ARG(crypt_volume_key_get
),
299 #if HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE
300 DLSYM_ARG(crypt_reencrypt_init_by_passphrase
),
302 #if HAVE_CRYPT_REENCRYPT
303 DLSYM_ARG(crypt_reencrypt
),
305 DLSYM_ARG(crypt_metadata_locking
),
306 #if HAVE_CRYPT_SET_DATA_OFFSET
307 DLSYM_ARG(crypt_set_data_offset
),
309 DLSYM_ARG(crypt_header_restore
),
310 DLSYM_ARG(crypt_volume_key_keyring
));
316 /* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
317 * libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
318 * whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
319 * other code loaded into this process also changes the global log functions of libcryptsetup, who
320 * knows? And if so, we still want our own objects to log via our own infra, at the very least.) */
321 cryptsetup_enable_logging(NULL
);
324 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "cryptsetup support is not compiled in.");
328 int cryptsetup_get_keyslot_from_token(JsonVariant
*v
) {
332 /* Parses the "keyslots" field of a LUKS2 token object. The field can be an array, but here we assume
333 * that it contains a single element only, since that's the only way we ever generate it
336 w
= json_variant_by_key(v
, "keyslots");
339 if (!json_variant_is_array(w
) || json_variant_elements(w
) != 1)
342 w
= json_variant_by_index(w
, 0);
345 if (!json_variant_is_string(w
))
348 r
= safe_atoi(json_variant_string(w
), &keyslot
);