1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "ask-password-api.h"
5 #include "cryptsetup-tpm2.h"
10 #include "parse-util.h"
11 #include "random-util.h"
13 #include "tpm2-util.h"
15 static int get_pin(usec_t until
, AskPasswordFlags ask_password_flags
, bool headless
, char **ret_pin_str
) {
16 _cleanup_free_
char *pin_str
= NULL
;
17 _cleanup_strv_free_erase_
char **pin
= NULL
;
22 r
= getenv_steal_erase("PIN", &pin_str
);
24 return log_error_errno(r
, "Failed to acquire PIN from environment: %m");
27 return log_error_errno(
28 SYNTHETIC_ERRNO(ENOPKG
),
29 "PIN querying disabled via 'headless' option. "
30 "Use the '$PIN' environment variable.");
32 pin
= strv_free_erase(pin
);
33 r
= ask_password_auto(
34 "Please enter TPM2 PIN:",
38 "cryptsetup.tpm2-pin",
43 return log_error_errno(r
, "Failed to ask for user pin: %m");
44 assert(strv_length(pin
) == 1);
46 pin_str
= strdup(pin
[0]);
51 *ret_pin_str
= TAKE_PTR(pin_str
);
57 const char *volume_name
,
59 uint32_t hash_pcr_mask
,
63 uint32_t pubkey_pcr_mask
,
64 const char *signature_path
,
68 uint64_t key_file_offset
,
71 const void *policy_hash
,
72 size_t policy_hash_size
,
78 AskPasswordFlags ask_password_flags
,
79 void **ret_decrypted_key
,
80 size_t *ret_decrypted_key_size
) {
82 _cleanup_(json_variant_unrefp
) JsonVariant
*signature_json
= NULL
;
83 _cleanup_free_
void *loaded_blob
= NULL
;
84 _cleanup_free_
char *auto_device
= NULL
;
90 r
= tpm2_find_device_auto(LOG_DEBUG
, &auto_device
);
92 return -EAGAIN
; /* Tell the caller to wait for a TPM2 device to show up */
101 blob_size
= key_data_size
;
103 _cleanup_free_
char *bindname
= NULL
;
105 /* If we read the salt via AF_UNIX, make this client recognizable */
106 if (asprintf(&bindname
, "@%" PRIx64
"/cryptsetup-tpm2/%s", random_u64(), volume_name
) < 0)
109 r
= read_full_file_full(
111 key_file_offset
== 0 ? UINT64_MAX
: key_file_offset
,
112 key_file_size
== 0 ? SIZE_MAX
: key_file_size
,
113 READ_FULL_FILE_CONNECT_SOCKET
,
115 (char**) &loaded_blob
, &blob_size
);
122 if (pubkey_pcr_mask
!= 0) {
123 r
= tpm2_load_pcr_signature(signature_path
, &signature_json
);
128 if (!(flags
& TPM2_FLAGS_USE_PIN
))
143 ret_decrypted_key_size
);
145 for (int i
= 5;; i
--) {
146 _cleanup_(erase_and_freep
) char *pin_str
= NULL
, *b64_salted_pin
= NULL
;
151 r
= get_pin(until
, ask_password_flags
, headless
, &pin_str
);
156 uint8_t salted_pin
[SHA256_DIGEST_SIZE
] = {};
157 CLEANUP_ERASE(salted_pin
);
159 r
= tpm2_util_pbkdf2_hmac_sha256(pin_str
, strlen(pin_str
), salt
, salt_size
, salted_pin
);
161 return log_error_errno(r
, "Failed to perform PBKDF2: %m");
163 r
= base64mem(salted_pin
, sizeof(salted_pin
), &b64_salted_pin
);
165 return log_error_errno(r
, "Failed to base64 encode salted pin: %m");
167 /* no salting needed, backwards compat with non-salted pins */
168 b64_salted_pin
= TAKE_PTR(pin_str
);
170 r
= tpm2_unseal(device
,
183 ret_decrypted_key_size
);
184 /* We get this error in case there is an authentication policy mismatch. This should
185 * not happen, but this avoids confusing behavior, just in case. */
186 if (IN_SET(r
, -EPERM
, -ENOLCK
))
195 int find_tpm2_auto_data(
196 struct crypt_device
*cd
,
197 uint32_t search_pcr_mask
,
199 uint32_t *ret_hash_pcr_mask
,
200 uint16_t *ret_pcr_bank
,
202 size_t *ret_pubkey_size
,
203 uint32_t *ret_pubkey_pcr_mask
,
204 uint16_t *ret_primary_alg
,
206 size_t *ret_blob_size
,
207 void **ret_policy_hash
,
208 size_t *ret_policy_hash_size
,
210 size_t *ret_salt_size
,
211 TPM2Flags
*ret_flags
,
219 for (token
= start_token
; token
< sym_crypt_token_max(CRYPT_LUKS2
); token
++) {
220 _cleanup_free_
void *blob
= NULL
, *policy_hash
= NULL
, *pubkey
= NULL
, *salt
= NULL
;
221 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
222 size_t blob_size
, policy_hash_size
, pubkey_size
, salt_size
= 0;
223 uint32_t hash_pcr_mask
, pubkey_pcr_mask
;
224 uint16_t pcr_bank
, primary_alg
;
228 r
= cryptsetup_get_token_as_json(cd
, token
, "systemd-tpm2", &v
);
229 if (IN_SET(r
, -ENOENT
, -EINVAL
, -EMEDIUMTYPE
))
232 return log_error_errno(r
, "Failed to read JSON token data off disk: %m");
234 r
= tpm2_parse_luks2_json(
239 &pubkey
, &pubkey_size
,
243 &policy_hash
, &policy_hash_size
,
246 if (r
== -EUCLEAN
) /* Gracefully handle issues in JSON fields not owned by us */
249 return log_error_errno(r
, "Failed to parse TPM2 JSON data: %m");
251 if (search_pcr_mask
== UINT32_MAX
||
252 search_pcr_mask
== hash_pcr_mask
) {
254 if (start_token
<= 0)
255 log_info("Automatically discovered security TPM2 token unlocks volume.");
257 *ret_hash_pcr_mask
= hash_pcr_mask
;
258 *ret_pcr_bank
= pcr_bank
;
259 *ret_pubkey
= TAKE_PTR(pubkey
);
260 *ret_pubkey_size
= pubkey_size
;
261 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
262 *ret_primary_alg
= primary_alg
;
263 *ret_blob
= TAKE_PTR(blob
);
264 *ret_blob_size
= blob_size
;
265 *ret_policy_hash
= TAKE_PTR(policy_hash
);
266 *ret_policy_hash_size
= policy_hash_size
;
267 *ret_salt
= TAKE_PTR(salt
);
268 *ret_salt_size
= salt_size
;
269 *ret_keyslot
= keyslot
;
275 /* PCR mask doesn't match what is configured, ignore this entry, let's see next */
278 return log_error_errno(SYNTHETIC_ERRNO(ENXIO
), "No valid TPM2 token data found.");