]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/cryptenroll/cryptenroll-pkcs11.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / cryptenroll / cryptenroll-pkcs11.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "cryptenroll-pkcs11.h"
4 #include "hexdecoct.h"
5 #include "json.h"
6 #include "memory-util.h"
7 #include "openssl-util.h"
8 #include "pkcs11-util.h"
9
10 int enroll_pkcs11(
11 struct crypt_device *cd,
12 const void *volume_key,
13 size_t volume_key_size,
14 const char *uri) {
15
16 _cleanup_(erase_and_freep) void *decrypted_key = NULL;
17 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
18 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
19 _cleanup_free_ char *keyslot_as_string = NULL;
20 size_t decrypted_key_size, saved_key_size;
21 _cleanup_free_ void *saved_key = NULL;
22 _cleanup_(X509_freep) X509 *cert = NULL;
23 ssize_t base64_encoded_size;
24 const char *node;
25 int keyslot, r;
26
27 assert_se(cd);
28 assert_se(volume_key);
29 assert_se(volume_key_size > 0);
30 assert_se(uri);
31
32 assert_se(node = crypt_get_device_name(cd));
33
34 r = pkcs11_acquire_certificate(uri, "volume enrollment operation", "drive-harddisk", &cert, NULL);
35 if (r < 0)
36 return r;
37
38 r = x509_generate_volume_keys(cert, &decrypted_key, &decrypted_key_size, &saved_key, &saved_key_size);
39 if (r < 0)
40 return log_error_errno(r, "Failed to generate volume keys: %m");
41
42 /* Let's base64 encode the key to use, for compat with homed (and it's easier to type it in by
43 * keyboard, if that might ever end up being necessary.) */
44 base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
45 if (base64_encoded_size < 0)
46 return log_error_errno(base64_encoded_size, "Failed to base64 encode secret key: %m");
47
48 r = cryptsetup_set_minimal_pbkdf(cd);
49 if (r < 0)
50 return log_error_errno(r, "Failed to set minimal PBKDF: %m");
51
52 keyslot = crypt_keyslot_add_by_volume_key(
53 cd,
54 CRYPT_ANY_SLOT,
55 volume_key,
56 volume_key_size,
57 base64_encoded,
58 base64_encoded_size);
59 if (keyslot < 0)
60 return log_error_errno(keyslot, "Failed to add new PKCS#11 key to %s: %m", node);
61
62 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
63 return log_oom();
64
65 r = json_build(&v,
66 JSON_BUILD_OBJECT(
67 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-pkcs11")),
68 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
69 JSON_BUILD_PAIR("pkcs11-uri", JSON_BUILD_STRING(uri)),
70 JSON_BUILD_PAIR("pkcs11-key", JSON_BUILD_BASE64(saved_key, saved_key_size))));
71 if (r < 0)
72 return log_error_errno(r, "Failed to prepare PKCS#11 JSON token object: %m");
73
74 r = cryptsetup_add_token_json(cd, v);
75 if (r < 0)
76 return log_error_errno(r, "Failed to add PKCS#11 JSON token to LUKS2 header: %m");
77
78 log_info("New PKCS#11 token enrolled as key slot %i.", keyslot);
79 return keyslot;
80 }