]>
Commit | Line | Data |
---|---|---|
8186022c OK |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include <errno.h> | |
4 | #include <libcryptsetup.h> | |
5 | ||
6 | #include "cryptsetup-token.h" | |
7 | #include "cryptsetup-token-util.h" | |
8 | #include "hexdecoct.h" | |
9 | #include "json.h" | |
10 | #include "luks2-pkcs11.h" | |
11 | #include "memory-util.h" | |
12 | #include "pkcs11-util.h" | |
13 | #include "version.h" | |
14 | ||
15 | #define TOKEN_NAME "systemd-pkcs11" | |
16 | #define TOKEN_VERSION_MAJOR "1" | |
17 | #define TOKEN_VERSION_MINOR "0" | |
18 | ||
19 | /* for libcryptsetup debug purpose */ | |
20 | _public_ const char *cryptsetup_token_version(void) { | |
21 | return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR " systemd-v" STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")"; | |
22 | } | |
23 | ||
24 | _public_ int cryptsetup_token_open_pin( | |
25 | struct crypt_device *cd, /* is always LUKS2 context */ | |
26 | int token /* is always >= 0 */, | |
27 | const char *pin, | |
28 | size_t pin_size, | |
29 | char **password, /* freed by cryptsetup_token_buffer_free */ | |
30 | size_t *password_len, | |
31 | void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) { | |
32 | ||
33 | const char *json; | |
34 | int r; | |
35 | ||
36 | assert(!pin || pin_size); | |
37 | assert(token >= 0); | |
38 | ||
39 | /* This must not fail at this moment (internal error) */ | |
40 | r = crypt_token_json_get(cd, token, &json); | |
dfe7cfe4 FS |
41 | /* Use assert_se() here to avoid emitting warning with -DNDEBUG */ |
42 | assert_se(token == r); | |
8186022c OK |
43 | assert(json); |
44 | ||
45 | return acquire_luks2_key(cd, json, usrptr, pin, pin_size, password, password_len); | |
46 | } | |
47 | ||
48 | /* | |
49 | * This function is called from within following libcryptsetup calls | |
50 | * provided conditions further below are met: | |
51 | * | |
52 | * crypt_activate_by_token(), crypt_activate_by_token_type(type == 'systemd-pkcs11'): | |
53 | * | |
54 | * - token is assigned to at least one luks2 keyslot eligible to activate LUKS2 device | |
55 | * (alternatively: name is set to null, flags contains CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY | |
56 | * and token is assigned to at least single keyslot). | |
57 | * | |
d4e30ad1 | 58 | * - if plugin defines validate function (see cryptsetup_token_validate below) it must have |
8186022c OK |
59 | * passed the check (aka return 0) |
60 | */ | |
61 | _public_ int cryptsetup_token_open( | |
62 | struct crypt_device *cd, /* is always LUKS2 context */ | |
63 | int token /* is always >= 0 */, | |
64 | char **password, /* freed by cryptsetup_token_buffer_free */ | |
65 | size_t *password_len, | |
66 | void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) { | |
67 | ||
68 | return cryptsetup_token_open_pin(cd, token, NULL, 0, password, password_len, usrptr); | |
69 | } | |
70 | ||
71 | /* | |
72 | * libcryptsetup callback for memory deallocation of 'password' parameter passed in | |
73 | * any crypt_token_open_* plugin function | |
74 | */ | |
75 | _public_ void cryptsetup_token_buffer_free(void *buffer, size_t buffer_len) { | |
76 | erase_and_free(buffer); | |
77 | } | |
78 | ||
79 | /* | |
80 | * prints systemd-pkcs11 token content in crypt_dump(). | |
81 | * 'type' and 'keyslots' fields are printed by libcryptsetup | |
82 | */ | |
83 | _public_ void cryptsetup_token_dump( | |
84 | struct crypt_device *cd /* is always LUKS2 context */, | |
85 | const char *json /* validated 'systemd-pkcs11' token if cryptsetup_token_validate is defined */) { | |
86 | ||
87 | int r; | |
88 | size_t pkcs11_key_size; | |
89 | _cleanup_free_ char *pkcs11_uri = NULL, *key_str = NULL; | |
90 | _cleanup_free_ void *pkcs11_key = NULL; | |
91 | ||
92 | r = parse_luks2_pkcs11_data(cd, json, &pkcs11_uri, &pkcs11_key, &pkcs11_key_size); | |
93 | if (r < 0) | |
94 | return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " metadata: %m."); | |
95 | ||
96 | r = crypt_dump_buffer_to_hex_string(pkcs11_key, pkcs11_key_size, &key_str); | |
97 | if (r < 0) | |
cee60fc3 | 98 | return (void) crypt_log_debug_errno(cd, r, "Cannot dump " TOKEN_NAME " content: %m"); |
8186022c OK |
99 | |
100 | crypt_log(cd, "\tpkcs11-uri: %s\n", pkcs11_uri); | |
101 | crypt_log(cd, "\tpkcs11-key: %s\n", key_str); | |
102 | } | |
103 | ||
104 | /* | |
105 | * Note: | |
106 | * If plugin is available in library path, it's called in before following libcryptsetup calls: | |
107 | * | |
108 | * crypt_token_json_set, crypt_dump, any crypt_activate_by_token_* flavour | |
109 | */ | |
110 | _public_ int cryptsetup_token_validate( | |
111 | struct crypt_device *cd, /* is always LUKS2 context */ | |
112 | const char *json /* contains valid 'type' and 'keyslots' fields. 'type' is 'systemd-pkcs11' */) { | |
113 | ||
114 | int r; | |
115 | JsonVariant *w; | |
116 | _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; | |
117 | ||
118 | r = json_parse(json, 0, &v, NULL, NULL); | |
119 | if (r < 0) | |
120 | return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m."); | |
121 | ||
122 | w = json_variant_by_key(v, "pkcs11-uri"); | |
123 | if (!w || !json_variant_is_string(w)) { | |
124 | crypt_log_debug(cd, "PKCS#11 token data lacks 'pkcs11-uri' field."); | |
125 | return 1; | |
126 | } | |
127 | ||
128 | if (!pkcs11_uri_valid(json_variant_string(w))) { | |
129 | crypt_log_debug(cd, "PKCS#11 token data contains invalid PKCS#11 URI."); | |
130 | return 1; | |
131 | } | |
132 | ||
133 | w = json_variant_by_key(v, "pkcs11-key"); | |
134 | if (!w || !json_variant_is_string(w)) { | |
135 | crypt_log_debug(cd, "PKCS#11 token data lacks 'pkcs11-key' field."); | |
136 | return 1; | |
137 | } | |
138 | ||
139 | r = unbase64mem(json_variant_string(w), SIZE_MAX, NULL, NULL); | |
140 | if (r < 0) | |
141 | return crypt_log_debug_errno(cd, r, "Failed to decode base64 encoded key: %m."); | |
142 | ||
143 | return 0; | |
144 | } |