]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/cryptsetup-util.c
cryptsetup-util: disable pbkdf benchmark in cryptsetup_set_minimal_pbkdf.
[thirdparty/systemd.git] / src / shared / cryptsetup-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #if HAVE_LIBCRYPTSETUP
4 #include "alloc-util.h"
5 #include "cryptsetup-util.h"
6 #include "dlfcn-util.h"
7 #include "log.h"
8 #include "parse-util.h"
9
10 static void *cryptsetup_dl = NULL;
11
12 int (*sym_crypt_activate_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags);
13 #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
14 int (*sym_crypt_activate_by_signed_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, const char *signature, size_t signature_size, uint32_t flags);
15 #endif
16 int (*sym_crypt_activate_by_volume_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, uint32_t flags);
17 int (*sym_crypt_deactivate_by_name)(struct crypt_device *cd, const char *name, uint32_t flags);
18 int (*sym_crypt_format)(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params);
19 void (*sym_crypt_free)(struct crypt_device *cd);
20 const char *(*sym_crypt_get_dir)(void);
21 int (*sym_crypt_get_verity_info)(struct crypt_device *cd, struct crypt_params_verity *vp);
22 int (*sym_crypt_init)(struct crypt_device **cd, const char *device);
23 int (*sym_crypt_init_by_name)(struct crypt_device **cd, const char *name);
24 int (*sym_crypt_keyslot_add_by_volume_key)(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size);
25 int (*sym_crypt_load)(struct crypt_device *cd, const char *requested_type, void *params);
26 int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_size);
27 int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device);
28 void (*sym_crypt_set_debug_level)(int level);
29 void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr);
30 int (*sym_crypt_set_pbkdf_type)(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf) = NULL;
31 int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json) = NULL;
32 int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json) = NULL;
33 int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
34 #if HAVE_CRYPT_TOKEN_MAX
35 int (*sym_crypt_token_max)(const char *type);
36 #endif
37
38 int dlopen_cryptsetup(void) {
39 _cleanup_(dlclosep) void *dl = NULL;
40 int r;
41
42 if (cryptsetup_dl)
43 return 0; /* Already loaded */
44
45 dl = dlopen("libcryptsetup.so.12", RTLD_LAZY);
46 if (!dl)
47 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
48 "libcryptsetup support is not installed: %s", dlerror());
49
50 r = dlsym_many_and_warn(
51 dl,
52 LOG_DEBUG,
53 DLSYM_ARG(crypt_activate_by_passphrase),
54 #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
55 DLSYM_ARG(crypt_activate_by_signed_key),
56 #endif
57 DLSYM_ARG(crypt_activate_by_volume_key),
58 DLSYM_ARG(crypt_deactivate_by_name),
59 DLSYM_ARG(crypt_format),
60 DLSYM_ARG(crypt_free),
61 DLSYM_ARG(crypt_get_dir),
62 DLSYM_ARG(crypt_get_verity_info),
63 DLSYM_ARG(crypt_init),
64 DLSYM_ARG(crypt_init_by_name),
65 DLSYM_ARG(crypt_keyslot_add_by_volume_key),
66 DLSYM_ARG(crypt_load),
67 DLSYM_ARG(crypt_resize),
68 DLSYM_ARG(crypt_set_data_device),
69 DLSYM_ARG(crypt_set_debug_level),
70 DLSYM_ARG(crypt_set_log_callback),
71 DLSYM_ARG(crypt_set_pbkdf_type),
72 DLSYM_ARG(crypt_token_json_get),
73 DLSYM_ARG(crypt_token_json_set),
74 DLSYM_ARG(crypt_volume_key_get),
75 #if HAVE_CRYPT_TOKEN_MAX
76 DLSYM_ARG(crypt_token_max),
77 #endif
78 NULL);
79 if (r < 0)
80 return r;
81
82 /* Note that we never release the reference here, because there's no real reason to, after all this
83 * was traditionally a regular shared library dependency which lives forever too. */
84 cryptsetup_dl = TAKE_PTR(dl);
85 return 1;
86 }
87
88 static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
89
90 switch (level) {
91 case CRYPT_LOG_NORMAL:
92 level = LOG_NOTICE;
93 break;
94 case CRYPT_LOG_ERROR:
95 level = LOG_ERR;
96 break;
97 case CRYPT_LOG_VERBOSE:
98 level = LOG_INFO;
99 break;
100 case CRYPT_LOG_DEBUG:
101 level = LOG_DEBUG;
102 break;
103 default:
104 log_error("Unknown libcryptsetup log level: %d", level);
105 level = LOG_ERR;
106 }
107
108 log_full(level, "%s", msg);
109 }
110
111 void cryptsetup_enable_logging(struct crypt_device *cd) {
112 if (!cd)
113 return;
114
115 if (dlopen_cryptsetup() < 0) /* If this fails, let's gracefully ignore the issue, this is just debug
116 * logging after all, and if this failed we already generated a debug
117 * log message that should help to track things down. */
118 return;
119
120 sym_crypt_set_log_callback(cd, cryptsetup_log_glue, NULL);
121 sym_crypt_set_debug_level(DEBUG_LOGGING ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
122 }
123
124 int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd) {
125
126 /* With CRYPT_PBKDF_NO_BENCHMARK flag set .time_ms member is ignored
127 * while .iterations must be set at least to recommended minimum value. */
128
129 static const struct crypt_pbkdf_type minimal_pbkdf = {
130 .hash = "sha512",
131 .type = CRYPT_KDF_PBKDF2,
132 .iterations = 1000, /* recommended minimum count for pbkdf2
133 * according to NIST SP 800-132, ch. 5.2 */
134 .flags = CRYPT_PBKDF_NO_BENCHMARK
135 };
136
137 int r;
138
139 /* Sets a minimal PKBDF in case we already have a high entropy key. */
140
141 r = dlopen_cryptsetup();
142 if (r < 0)
143 return r;
144
145 r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf);
146 if (r < 0)
147 return r;
148
149 return 0;
150 }
151
152 int cryptsetup_get_token_as_json(
153 struct crypt_device *cd,
154 int idx,
155 const char *verify_type,
156 JsonVariant **ret) {
157
158 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
159 const char *text;
160 int r;
161
162 assert(cd);
163
164 /* Extracts and parses the LUKS2 JSON token data from a LUKS2 device. Optionally verifies the type of
165 * the token. Returns:
166 *
167 * -EINVAL → token index out of range or "type" field missing
168 * -ENOENT → token doesn't exist
169 * -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type
170 */
171
172 r = dlopen_cryptsetup();
173 if (r < 0)
174 return r;
175
176 r = sym_crypt_token_json_get(cd, idx, &text);
177 if (r < 0)
178 return r;
179
180 r = json_parse(text, 0, &v, NULL, NULL);
181 if (r < 0)
182 return r;
183
184 if (verify_type) {
185 JsonVariant *w;
186
187 w = json_variant_by_key(v, "type");
188 if (!w)
189 return -EINVAL;
190
191 if (!streq_ptr(json_variant_string(w), verify_type))
192 return -EMEDIUMTYPE;
193 }
194
195 if (ret)
196 *ret = TAKE_PTR(v);
197
198 return 0;
199 }
200
201 int cryptsetup_get_keyslot_from_token(JsonVariant *v) {
202 int keyslot, r;
203 JsonVariant *w;
204
205 /* Parses the "keyslots" field of a LUKS2 token object. The field can be an array, but here we assume
206 * that it contains a single element only, since that's the only way we ever generate it
207 * ourselves. */
208
209 w = json_variant_by_key(v, "keyslots");
210 if (!w)
211 return -ENOENT;
212 if (!json_variant_is_array(w) || json_variant_elements(w) != 1)
213 return -EMEDIUMTYPE;
214
215 w = json_variant_by_index(w, 0);
216 if (!w)
217 return -ENOENT;
218 if (!json_variant_is_string(w))
219 return -EMEDIUMTYPE;
220
221 r = safe_atoi(json_variant_string(w), &keyslot);
222 if (r < 0)
223 return r;
224 if (keyslot < 0)
225 return -EINVAL;
226
227 return keyslot;
228 }
229
230 int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v) {
231 _cleanup_free_ char *text = NULL;
232 int r;
233
234 r = dlopen_cryptsetup();
235 if (r < 0)
236 return r;
237
238 r = json_variant_format(v, 0, &text);
239 if (r < 0)
240 return log_debug_errno(r, "Failed to format token data for LUKS: %m");
241
242 log_debug("Adding token text <%s>", text);
243
244 r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
245 if (r < 0)
246 return log_debug_errno(r, "Failed to write token data to LUKS: %m");
247
248 return 0;
249 }
250 #endif