]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/tpm2-util.c
tpm2-util: split out code that checks if bank has 24 pcrs into helper function of...
[thirdparty/systemd.git] / src / shared / tpm2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "alloc-util.h"
4 #include "cryptsetup-util.h"
5 #include "def.h"
6 #include "dirent-util.h"
7 #include "dlfcn-util.h"
8 #include "efi-api.h"
9 #include "extract-word.h"
10 #include "fd-util.h"
11 #include "fileio.h"
12 #include "format-table.h"
13 #include "fs-util.h"
14 #include "hexdecoct.h"
15 #include "memory-util.h"
16 #include "openssl-util.h"
17 #include "parse-util.h"
18 #include "random-util.h"
19 #include "sha256.h"
20 #include "stat-util.h"
21 #include "time-util.h"
22 #include "tpm2-util.h"
23 #include "virt.h"
24
25 #if HAVE_TPM2
26 static void *libtss2_esys_dl = NULL;
27 static void *libtss2_rc_dl = NULL;
28 static void *libtss2_mu_dl = NULL;
29
30 TSS2_RC (*sym_Esys_Create)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, TPM2B_PRIVATE **outPrivate, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
31 TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR primaryHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, ESYS_TR *objectHandle, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
32 void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
33 TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
34 void (*sym_Esys_Free)(void *ptr) = NULL;
35 TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData);
36 TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
37 TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
38 TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle) = NULL;
39 TSS2_RC (*sym_Esys_LoadExternal)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR hierarchy, ESYS_TR *objectHandle);
40 TSS2_RC (*sym_Esys_PCR_Extend)(ESYS_CONTEXT *esysContext, ESYS_TR pcrHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST_VALUES *digests);
41 TSS2_RC (*sym_Esys_PCR_Read)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1,ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues);
42 TSS2_RC (*sym_Esys_PolicyAuthorize)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *approvedPolicy, const TPM2B_NONCE *policyRef, const TPM2B_NAME *keySign, const TPMT_TK_VERIFIED *checkTicket);
43 TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
44 TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
45 TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL;
46 TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL;
47 TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
48 TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask);
49 TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name);
50 TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
51 TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
52 TSS2_RC (*sym_Esys_VerifySignature)(ESYS_CONTEXT *esysContext, ESYS_TR keyHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *digest, const TPMT_SIGNATURE *signature, TPMT_TK_VERIFIED **validation);
53
54 const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
55
56 TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
57 TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
58 TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
59 TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
60
61 int dlopen_tpm2(void) {
62 int r;
63
64 r = dlopen_many_sym_or_warn(
65 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
66 DLSYM_ARG(Esys_Create),
67 DLSYM_ARG(Esys_CreatePrimary),
68 DLSYM_ARG(Esys_Finalize),
69 DLSYM_ARG(Esys_FlushContext),
70 DLSYM_ARG(Esys_Free),
71 DLSYM_ARG(Esys_GetCapability),
72 DLSYM_ARG(Esys_GetRandom),
73 DLSYM_ARG(Esys_Initialize),
74 DLSYM_ARG(Esys_Load),
75 DLSYM_ARG(Esys_LoadExternal),
76 DLSYM_ARG(Esys_PCR_Extend),
77 DLSYM_ARG(Esys_PCR_Read),
78 DLSYM_ARG(Esys_PolicyAuthorize),
79 DLSYM_ARG(Esys_PolicyAuthValue),
80 DLSYM_ARG(Esys_PolicyGetDigest),
81 DLSYM_ARG(Esys_PolicyPCR),
82 DLSYM_ARG(Esys_StartAuthSession),
83 DLSYM_ARG(Esys_Startup),
84 DLSYM_ARG(Esys_TRSess_SetAttributes),
85 DLSYM_ARG(Esys_TR_GetName),
86 DLSYM_ARG(Esys_TR_SetAuth),
87 DLSYM_ARG(Esys_Unseal),
88 DLSYM_ARG(Esys_VerifySignature));
89 if (r < 0)
90 return r;
91
92 r = dlopen_many_sym_or_warn(
93 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
94 DLSYM_ARG(Tss2_RC_Decode));
95 if (r < 0)
96 return r;
97
98 return dlopen_many_sym_or_warn(
99 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
100 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
101 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
102 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
103 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal));
104 }
105
106 void tpm2_context_destroy(struct tpm2_context *c) {
107 assert(c);
108
109 if (c->esys_context)
110 sym_Esys_Finalize(&c->esys_context);
111
112 c->tcti_context = mfree(c->tcti_context);
113
114 if (c->tcti_dl) {
115 dlclose(c->tcti_dl);
116 c->tcti_dl = NULL;
117 }
118 }
119
120 static inline void Esys_Finalize_wrapper(ESYS_CONTEXT **c) {
121 /* A wrapper around Esys_Finalize() for use with _cleanup_(). Only reasons we need this wrapper is
122 * because the function itself warn logs if we'd pass a pointer to NULL, and we don't want that. */
123 if (*c)
124 sym_Esys_Finalize(c);
125 }
126
127 ESYS_TR tpm2_flush_context_verbose(ESYS_CONTEXT *c, ESYS_TR handle) {
128 TSS2_RC rc;
129
130 if (!c || handle == ESYS_TR_NONE)
131 return ESYS_TR_NONE;
132
133 rc = sym_Esys_FlushContext(c, handle);
134 if (rc != TSS2_RC_SUCCESS) /* We ignore failures here (besides debug logging), since this is called
135 * in error paths, where we cannot do anything about failures anymore. And
136 * when it is called in successful codepaths by this time we already did
137 * what we wanted to do, and got the results we wanted so there's no
138 * reason to make this fail more loudly than necessary. */
139 log_debug("Failed to get flush context of TPM, ignoring: %s", sym_Tss2_RC_Decode(rc));
140
141 return ESYS_TR_NONE;
142 }
143
144 int tpm2_context_init(const char *device, struct tpm2_context *ret) {
145 _cleanup_(Esys_Finalize_wrapper) ESYS_CONTEXT *c = NULL;
146 _cleanup_free_ TSS2_TCTI_CONTEXT *tcti = NULL;
147 _cleanup_(dlclosep) void *dl = NULL;
148 TSS2_RC rc;
149 int r;
150
151 r = dlopen_tpm2();
152 if (r < 0)
153 return log_error_errno(r, "TPM2 support not installed: %m");
154
155 if (!device)
156 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
157
158 if (device) {
159 const char *param, *driver, *fn;
160 const TSS2_TCTI_INFO* info;
161 TSS2_TCTI_INFO_FUNC func;
162 size_t sz = 0;
163
164 param = strchr(device, ':');
165 if (param) {
166 driver = strndupa_safe(device, param - device);
167 param++;
168 } else {
169 driver = "device";
170 param = device;
171 }
172
173 fn = strjoina("libtss2-tcti-", driver, ".so.0");
174
175 dl = dlopen(fn, RTLD_NOW);
176 if (!dl)
177 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
178
179 func = dlsym(dl, TSS2_TCTI_INFO_SYMBOL);
180 if (!func)
181 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
182 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
183 dlerror());
184
185 info = func();
186 if (!info)
187 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
188
189
190 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
191
192 rc = info->init(NULL, &sz, NULL);
193 if (rc != TPM2_RC_SUCCESS)
194 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
195 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
196
197 tcti = malloc0(sz);
198 if (!tcti)
199 return log_oom();
200
201 rc = info->init(tcti, &sz, param);
202 if (rc != TPM2_RC_SUCCESS)
203 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
204 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
205 }
206
207 rc = sym_Esys_Initialize(&c, tcti, NULL);
208 if (rc != TSS2_RC_SUCCESS)
209 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
210 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
211
212 rc = sym_Esys_Startup(c, TPM2_SU_CLEAR);
213 if (rc == TPM2_RC_INITIALIZE)
214 log_debug("TPM already started up.");
215 else if (rc == TSS2_RC_SUCCESS)
216 log_debug("TPM successfully started up.");
217 else
218 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
219 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
220
221 *ret = (struct tpm2_context) {
222 .esys_context = TAKE_PTR(c),
223 .tcti_context = TAKE_PTR(tcti),
224 .tcti_dl = TAKE_PTR(dl),
225 };
226
227 return 0;
228 }
229
230 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
231
232 static int tpm2_credit_random(ESYS_CONTEXT *c) {
233 size_t rps, done = 0;
234 TSS2_RC rc;
235 usec_t t;
236 int r;
237
238 assert(c);
239
240 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
241 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
242 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
243 * any entropy. */
244
245 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
246 if (errno != ENOENT)
247 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
248 } else {
249 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
250 return 0; /* Already done */
251 }
252
253 t = now(CLOCK_MONOTONIC);
254
255 for (rps = random_pool_size(); rps > 0;) {
256 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
257
258 rc = sym_Esys_GetRandom(
259 c,
260 ESYS_TR_NONE,
261 ESYS_TR_NONE,
262 ESYS_TR_NONE,
263 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
264 &buffer);
265 if (rc != TSS2_RC_SUCCESS)
266 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
267 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
268
269 if (buffer->size == 0)
270 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
271 "Zero-sized entropy returned from TPM.");
272
273 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
274 if (r < 0)
275 return log_error_errno(r, "Failed wo write entropy to kernel: %m");
276
277 done += buffer->size;
278 rps = LESS_BY(rps, buffer->size);
279 }
280
281 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
282
283 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
284 if (r < 0)
285 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
286
287 return 0;
288 }
289
290 static int tpm2_make_primary(
291 ESYS_CONTEXT *c,
292 ESYS_TR *ret_primary,
293 TPMI_ALG_PUBLIC alg,
294 TPMI_ALG_PUBLIC *ret_alg) {
295
296 static const TPM2B_SENSITIVE_CREATE primary_sensitive = {};
297 static const TPM2B_PUBLIC primary_template_ecc = {
298 .size = sizeof(TPMT_PUBLIC),
299 .publicArea = {
300 .type = TPM2_ALG_ECC,
301 .nameAlg = TPM2_ALG_SHA256,
302 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
303 .parameters.eccDetail = {
304 .symmetric = {
305 .algorithm = TPM2_ALG_AES,
306 .keyBits.aes = 128,
307 .mode.aes = TPM2_ALG_CFB,
308 },
309 .scheme.scheme = TPM2_ALG_NULL,
310 .curveID = TPM2_ECC_NIST_P256,
311 .kdf.scheme = TPM2_ALG_NULL,
312 },
313 },
314 };
315 static const TPM2B_PUBLIC primary_template_rsa = {
316 .size = sizeof(TPMT_PUBLIC),
317 .publicArea = {
318 .type = TPM2_ALG_RSA,
319 .nameAlg = TPM2_ALG_SHA256,
320 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
321 .parameters.rsaDetail = {
322 .symmetric = {
323 .algorithm = TPM2_ALG_AES,
324 .keyBits.aes = 128,
325 .mode.aes = TPM2_ALG_CFB,
326 },
327 .scheme.scheme = TPM2_ALG_NULL,
328 .keyBits = 2048,
329 },
330 },
331 };
332
333 static const TPML_PCR_SELECTION creation_pcr = {};
334 ESYS_TR primary = ESYS_TR_NONE;
335 TSS2_RC rc;
336 usec_t ts;
337
338 log_debug("Creating primary key on TPM.");
339
340 /* So apparently not all TPM2 devices support ECC. ECC is generally preferably, because it's so much
341 * faster, noticeably so (~10s vs. ~240ms on my system). Hence, unless explicitly configured let's
342 * try to use ECC first, and if that does not work, let's fall back to RSA. */
343
344 ts = now(CLOCK_MONOTONIC);
345
346 if (IN_SET(alg, 0, TPM2_ALG_ECC)) {
347 rc = sym_Esys_CreatePrimary(
348 c,
349 ESYS_TR_RH_OWNER,
350 ESYS_TR_PASSWORD,
351 ESYS_TR_NONE,
352 ESYS_TR_NONE,
353 &primary_sensitive,
354 &primary_template_ecc,
355 NULL,
356 &creation_pcr,
357 &primary,
358 NULL,
359 NULL,
360 NULL,
361 NULL);
362
363 if (rc != TSS2_RC_SUCCESS) {
364 if (alg != 0)
365 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
366 "Failed to generate ECC primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
367
368 log_debug("Failed to generate ECC primary key in TPM, trying RSA: %s", sym_Tss2_RC_Decode(rc));
369 } else {
370 log_debug("Successfully created ECC primary key on TPM.");
371 alg = TPM2_ALG_ECC;
372 }
373 }
374
375 if (IN_SET(alg, 0, TPM2_ALG_RSA)) {
376 rc = sym_Esys_CreatePrimary(
377 c,
378 ESYS_TR_RH_OWNER,
379 ESYS_TR_PASSWORD,
380 ESYS_TR_NONE,
381 ESYS_TR_NONE,
382 &primary_sensitive,
383 &primary_template_rsa,
384 NULL,
385 &creation_pcr,
386 &primary,
387 NULL,
388 NULL,
389 NULL,
390 NULL);
391 if (rc != TSS2_RC_SUCCESS)
392 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
393 "Failed to generate RSA primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
394 else if (alg == 0) {
395 log_notice("TPM2 chip apparently does not support ECC primary keys, falling back to RSA. "
396 "This likely means TPM2 operations will be relatively slow, please be patient.");
397 alg = TPM2_ALG_RSA;
398 }
399
400 log_debug("Successfully created RSA primary key on TPM.");
401 }
402
403 log_debug("Generating primary key on TPM2 took %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
404
405 *ret_primary = primary;
406 if (ret_alg)
407 *ret_alg = alg;
408
409 return 0;
410 }
411
412 void tpm2_pcr_mask_to_selection(uint32_t mask, uint16_t bank, TPML_PCR_SELECTION *ret) {
413 assert(ret);
414
415 /* We only do 24bit here, as that's what PC TPMs are supposed to support */
416 assert(mask <= 0xFFFFFFU);
417
418 *ret = (TPML_PCR_SELECTION) {
419 .count = 1,
420 .pcrSelections[0] = {
421 .hash = bank,
422 .sizeofSelect = 3,
423 .pcrSelect[0] = mask & 0xFF,
424 .pcrSelect[1] = (mask >> 8) & 0xFF,
425 .pcrSelect[2] = (mask >> 16) & 0xFF,
426 }
427 };
428 }
429
430 static unsigned find_nth_bit(uint32_t mask, unsigned n) {
431 uint32_t bit = 1;
432
433 assert(n < 32);
434
435 /* Returns the bit index of the nth set bit, e.g. mask=0b101001, n=3 → 5 */
436
437 for (unsigned i = 0; i < sizeof(mask)*8; i++) {
438
439 if (bit & mask) {
440 if (n == 0)
441 return i;
442
443 n--;
444 }
445
446 bit <<= 1;
447 }
448
449 return UINT_MAX;
450 }
451
452 static int tpm2_pcr_mask_good(
453 ESYS_CONTEXT *c,
454 TPMI_ALG_HASH bank,
455 uint32_t mask) {
456
457 _cleanup_(Esys_Freep) TPML_DIGEST *pcr_values = NULL;
458 TPML_PCR_SELECTION selection;
459 bool good = false;
460 TSS2_RC rc;
461
462 assert(c);
463
464 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
465 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
466 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
467
468 tpm2_pcr_mask_to_selection(mask, bank, &selection);
469
470 rc = sym_Esys_PCR_Read(
471 c,
472 ESYS_TR_NONE,
473 ESYS_TR_NONE,
474 ESYS_TR_NONE,
475 &selection,
476 NULL,
477 NULL,
478 &pcr_values);
479 if (rc != TSS2_RC_SUCCESS)
480 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
481 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
482
483 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
484 for (unsigned i = 0; i < pcr_values->count; i++) {
485 if (DEBUG_LOGGING) {
486 _cleanup_free_ char *h = NULL;
487 unsigned j;
488
489 h = hexmem(pcr_values->digests[i].buffer, pcr_values->digests[i].size);
490 j = find_nth_bit(mask, i);
491 assert(j != UINT_MAX);
492
493 log_debug("PCR %u value: %s", j, strna(h));
494 }
495
496 if (!memeqbyte(0x00, pcr_values->digests[i].buffer, pcr_values->digests[i].size) &&
497 !memeqbyte(0xFF, pcr_values->digests[i].buffer, pcr_values->digests[i].size))
498 good = true;
499 }
500
501 return good;
502 }
503
504 static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
505
506 assert(selection);
507
508 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
509 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
510 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
511 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
512 strna(tpm2_pcr_bank_to_string(selection->hash)));
513 return false;
514 }
515
516 assert_cc(TPM2_PCRS_MAX % 8 == 0);
517
518 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
519 * enabled for this bank. Otherwise this TPM doesn't qualify. */
520 bool valid = true;
521 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
522 if (selection->pcrSelect[j] != 0xFF) {
523 valid = false;
524 break;
525 }
526
527 if (!valid)
528 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
529 strna(tpm2_pcr_bank_to_string(selection->hash)));
530
531 return valid;
532 }
533
534 static int tpm2_get_best_pcr_bank(
535 ESYS_CONTEXT *c,
536 uint32_t pcr_mask,
537 TPMI_ALG_HASH *ret) {
538
539 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
540 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
541 TPMI_YES_NO more;
542 TSS2_RC rc;
543 int r;
544
545 assert(c);
546
547 rc = sym_Esys_GetCapability(
548 c,
549 ESYS_TR_NONE,
550 ESYS_TR_NONE,
551 ESYS_TR_NONE,
552 TPM2_CAP_PCRS,
553 0,
554 1,
555 &more,
556 &pcap);
557 if (rc != TSS2_RC_SUCCESS)
558 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
559 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
560
561 assert(pcap->capability == TPM2_CAP_PCRS);
562
563 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
564 int good;
565
566 /* For now we are only interested in the SHA1 and SHA256 banks */
567 if (!IN_SET(pcap->data.assignedPCR.pcrSelections[i].hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
568 continue;
569
570 r = tpm2_bank_has24(pcap->data.assignedPCR.pcrSelections + i);
571 if (r < 0)
572 return r;
573 if (!r)
574 continue;
575
576 good = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
577 if (good < 0)
578 return good;
579
580 if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) {
581 supported_hash = TPM2_ALG_SHA256;
582 if (good) {
583 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
584 hash_with_valid_pcr = TPM2_ALG_SHA256;
585 break;
586 }
587 } else {
588 assert(pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1);
589
590 if (supported_hash == 0)
591 supported_hash = TPM2_ALG_SHA1;
592
593 if (good && hash_with_valid_pcr == 0)
594 hash_with_valid_pcr = TPM2_ALG_SHA1;
595 }
596 }
597
598 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
599 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
600 * SHA1.
601 *
602 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
603 * not initialized. */
604
605 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
606 assert(supported_hash == TPM2_ALG_SHA256);
607 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
608 *ret = TPM2_ALG_SHA256;
609 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
610 if (supported_hash == TPM2_ALG_SHA256)
611 log_notice("TPM2 device supports both SHA1 and SHA256 PCR banks, but only SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
612 else {
613 assert(supported_hash == TPM2_ALG_SHA1);
614 log_notice("TPM2 device lacks support for SHA256 PCR bank, but SHA1 bank is supported and SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
615 }
616
617 *ret = TPM2_ALG_SHA1;
618 } else if (supported_hash == TPM2_ALG_SHA256) {
619 log_notice("TPM2 device supports SHA256 PCR bank but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA256 bank. PCR policy effectively unenforced!");
620 *ret = TPM2_ALG_SHA256;
621 } else if (supported_hash == TPM2_ALG_SHA1) {
622 log_notice("TPM2 device lacks support for SHA256 bank, but SHA1 bank is supported, but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA1 bank. PCR policy effectively unenforced!");
623 *ret = TPM2_ALG_SHA1;
624 } else
625 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
626 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
627
628 return 0;
629 }
630
631 static void hash_pin(const char *pin, size_t len, TPM2B_AUTH *auth) {
632 struct sha256_ctx hash;
633
634 assert(auth);
635 assert(pin);
636 auth->size = SHA256_DIGEST_SIZE;
637
638 sha256_init_ctx(&hash);
639 sha256_process_bytes(pin, len, &hash);
640 sha256_finish_ctx(&hash, auth->buffer);
641
642 explicit_bzero_safe(&hash, sizeof(hash));
643 }
644
645 static int tpm2_make_encryption_session(
646 ESYS_CONTEXT *c,
647 ESYS_TR primary,
648 ESYS_TR bind_key,
649 const char *pin,
650 ESYS_TR *ret_session) {
651
652 static const TPMT_SYM_DEF symmetric = {
653 .algorithm = TPM2_ALG_AES,
654 .keyBits.aes = 128,
655 .mode.aes = TPM2_ALG_CFB,
656 };
657 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
658 TPMA_SESSION_CONTINUESESSION;
659 ESYS_TR session = ESYS_TR_NONE;
660 TSS2_RC rc;
661
662 assert(c);
663
664 /*
665 * if a pin is set for the seal object, use it to bind the session
666 * key to that object. This prevents active bus interposers from
667 * faking a TPM and seeing the unsealed value. An active interposer
668 * could fake a TPM, satisfying the encrypted session, and just
669 * forward everything to the *real* TPM.
670 */
671 if (pin) {
672 TPM2B_AUTH auth = {};
673
674 hash_pin(pin, strlen(pin), &auth);
675
676 rc = sym_Esys_TR_SetAuth(c, bind_key, &auth);
677 /* ESAPI knows about it, so clear it from our memory */
678 explicit_bzero_safe(&auth, sizeof(auth));
679 if (rc != TSS2_RC_SUCCESS)
680 return log_error_errno(
681 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
682 "Failed to load PIN in TPM: %s",
683 sym_Tss2_RC_Decode(rc));
684 }
685
686 log_debug("Starting HMAC encryption session.");
687
688 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
689 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
690 * recover the salt, which is then used for key derivation. */
691 rc = sym_Esys_StartAuthSession(
692 c,
693 primary,
694 bind_key,
695 ESYS_TR_NONE,
696 ESYS_TR_NONE,
697 ESYS_TR_NONE,
698 NULL,
699 TPM2_SE_HMAC,
700 &symmetric,
701 TPM2_ALG_SHA256,
702 &session);
703 if (rc != TSS2_RC_SUCCESS)
704 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
705 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
706
707 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
708 * always used for sessions), this provides confidentiality, integrity and replay protection for
709 * operations that use this session. */
710 rc = sym_Esys_TRSess_SetAttributes(c, session, sessionAttributes, 0xff);
711 if (rc != TSS2_RC_SUCCESS)
712 return log_error_errno(
713 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
714 "Failed to configure TPM session: %s",
715 sym_Tss2_RC_Decode(rc));
716
717 if (ret_session) {
718 *ret_session = session;
719 session = ESYS_TR_NONE;
720 }
721
722 session = tpm2_flush_context_verbose(c, session);
723 return 0;
724 }
725
726 static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output) {
727 #if OPENSSL_VERSION_MAJOR >= 3
728 _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL;
729 #else
730 const BIGNUM *n = NULL, *e = NULL;
731 const RSA *rsa = NULL;
732 #endif
733 int n_bytes, e_bytes;
734
735 assert(input);
736 assert(output);
737
738 /* Converts an OpenSSL public key to a structure that the TPM chip can process. */
739
740 if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA)
741 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key.");
742
743 #if OPENSSL_VERSION_MAJOR >= 3
744 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_N, &n))
745 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
746 #else
747 rsa = EVP_PKEY_get0_RSA(input);
748 if (!rsa)
749 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to extract RSA key from public key.");
750
751 n = RSA_get0_n(rsa);
752 if (!n)
753 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
754 #endif
755
756 n_bytes = BN_num_bytes(n);
757 assert_se(n_bytes > 0);
758 if ((size_t) n_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.unique.rsa.buffer))
759 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA modulus too large for TPM2 public key object.");
760
761 #if OPENSSL_VERSION_MAJOR >= 3
762 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_E, &e))
763 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
764 #else
765 e = RSA_get0_e(rsa);
766 if (!e)
767 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
768 #endif
769
770 e_bytes = BN_num_bytes(e);
771 assert_se(e_bytes > 0);
772 if ((size_t) e_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.parameters.rsaDetail.exponent))
773 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA exponent too large for TPM2 public key object.");
774
775 *output = (TPM2B_PUBLIC) {
776 .size = sizeof(TPMT_PUBLIC),
777 .publicArea = {
778 .type = TPM2_ALG_RSA,
779 .nameAlg = TPM2_ALG_SHA256,
780 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
781 .parameters.rsaDetail = {
782 .scheme = {
783 .scheme = TPM2_ALG_NULL,
784 .details.anySig.hashAlg = TPM2_ALG_NULL,
785 },
786 .symmetric = {
787 .algorithm = TPM2_ALG_NULL,
788 .mode.sym = TPM2_ALG_NULL,
789 },
790 .keyBits = n_bytes * 8,
791 /* .exponent will be filled in below. */
792 },
793 .unique = {
794 .rsa.size = n_bytes,
795 /* .rsa.buffer will be filled in below. */
796 },
797 },
798 };
799
800 if (BN_bn2bin(n, output->publicArea.unique.rsa.buffer) <= 0)
801 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA modulus.");
802
803 if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0)
804 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent.");
805
806 return 0;
807 }
808
809 static int find_signature(
810 JsonVariant *v,
811 uint16_t pcr_bank,
812 uint32_t pcr_mask,
813 EVP_PKEY *pk,
814 const void *policy,
815 size_t policy_size,
816 void *ret_signature,
817 size_t *ret_signature_size) {
818
819 _cleanup_free_ void *fp = NULL;
820 JsonVariant *b, *i;
821 size_t fp_size;
822 const char *k;
823 int r;
824
825 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
826 * public key, and policy digest. */
827
828 if (!json_variant_is_object(v))
829 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
830
831 k = tpm2_pcr_bank_to_string(pcr_bank);
832 if (!k)
833 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
834
835 /* First, find field by bank */
836 b = json_variant_by_key(v, k);
837 if (!b)
838 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
839
840 if (!json_variant_is_array(b))
841 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
842
843 /* Now iterate through all signatures known for this bank */
844 JSON_VARIANT_ARRAY_FOREACH(i, b) {
845 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
846 JsonVariant *maskj, *fpj, *sigj, *polj;
847 size_t fpj_size, polj_size;
848 uint32_t parsed_mask;
849
850 if (!json_variant_is_object(i))
851 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
852
853 /* Check if the PCR mask matches our expectations */
854 maskj = json_variant_by_key(i, "pcrs");
855 if (!maskj)
856 continue;
857
858 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
859 if (r < 0)
860 return log_error_errno(r, "Failed to parse JSON PCR mask");
861
862 if (parsed_mask != pcr_mask)
863 continue; /* Not for this PCR mask */
864
865 /* Then check if this is for the public key we operate with */
866 fpj = json_variant_by_key(i, "pkfp");
867 if (!fpj)
868 continue;
869
870 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
871 if (r < 0)
872 return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
873
874 if (!fp) {
875 r = pubkey_fingerprint(pk, EVP_sha256(), &fp, &fp_size);
876 if (r < 0)
877 return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
878 }
879
880 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
881 continue; /* Not for this public key */
882
883 /* Finally, check if this is for the PCR policy we expect this to be */
884 polj = json_variant_by_key(i, "pol");
885 if (!polj)
886 continue;
887
888 r = json_variant_unhex(polj, &polj_data, &polj_size);
889 if (r < 0)
890 return log_error_errno(r, "Failed to decode policy hash JSON data: %m");
891
892 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
893 continue;
894
895 /* This entry matches all our expectations, now return the signature included in it */
896 sigj = json_variant_by_key(i, "sig");
897 if (!sigj)
898 continue;
899
900 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
901 }
902
903 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
904 }
905
906 static int tpm2_make_policy_session(
907 ESYS_CONTEXT *c,
908 ESYS_TR primary,
909 ESYS_TR parent_session,
910 TPM2_SE session_type,
911 uint32_t hash_pcr_mask,
912 uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
913 const void *pubkey,
914 size_t pubkey_size,
915 uint32_t pubkey_pcr_mask,
916 JsonVariant *signature_json,
917 bool use_pin,
918 ESYS_TR *ret_session,
919 TPM2B_DIGEST **ret_policy_digest,
920 TPMI_ALG_HASH *ret_pcr_bank) {
921
922 static const TPMT_SYM_DEF symmetric = {
923 .algorithm = TPM2_ALG_AES,
924 .keyBits.aes = 128,
925 .mode.aes = TPM2_ALG_CFB,
926 };
927 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
928 ESYS_TR session = ESYS_TR_NONE, pubkey_handle = ESYS_TR_NONE;
929 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
930 TSS2_RC rc;
931 int r;
932
933 assert(c);
934 assert(pubkey || pubkey_size == 0);
935 assert(pubkey_pcr_mask == 0 || pubkey_size > 0);
936
937 log_debug("Starting authentication session.");
938
939 /* So apparently some TPM implementations don't implement trial mode correctly. To avoid issues let's
940 * avoid it when it is easy to. At the moment we only really need trial mode for the signed PCR
941 * policies (since only then we need to shove PCR values into the policy that don't match current
942 * state anyway), hence if we have none of those we don't need to bother. Hence, let's patch in
943 * TPM2_SE_POLICY even if trial mode is requested unless a pubkey PCR mask is specified that is
944 * non-zero, i.e. signed PCR policy is requested.
945 *
946 * One day we should switch to calculating policy hashes client side when trial mode is requested, to
947 * avoid this mess. */
948 if (session_type == TPM2_SE_TRIAL && pubkey_pcr_mask == 0)
949 session_type = TPM2_SE_POLICY;
950
951 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
952 /* We are told to configure a PCR policy of some form, let's determine/validate the PCR bank to use. */
953
954 if (pcr_bank != UINT16_MAX) {
955 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
956 if (r < 0)
957 return r;
958 if (r == 0)
959 log_warning("Selected TPM2 PCRs are not initialized on this system, most likely due to a firmware issue. PCR policy is effectively not enforced. Proceeding anyway.");
960 } else {
961 /* No bank configured, pick automatically. Some TPM2 devices only can do SHA1. If we
962 * detect that use that, but preferably use SHA256 */
963 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
964 if (r < 0)
965 return r;
966 }
967 }
968
969 if (pubkey_size > 0) {
970 /* If a pubkey is specified, load it to validate it, even if the PCR mask for this is actually zero, and we are thus not going to use it. */
971 _cleanup_fclose_ FILE *f = fmemopen((void*) pubkey, pubkey_size, "r");
972 if (!f)
973 return log_oom();
974
975 pk = PEM_read_PUBKEY(f, NULL, NULL, NULL);
976 if (!pk)
977 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
978 }
979
980 rc = sym_Esys_StartAuthSession(
981 c,
982 primary,
983 ESYS_TR_NONE,
984 parent_session,
985 ESYS_TR_NONE,
986 ESYS_TR_NONE,
987 NULL,
988 session_type,
989 &symmetric,
990 TPM2_ALG_SHA256,
991 &session);
992 if (rc != TSS2_RC_SUCCESS)
993 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
994 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
995
996 if (pubkey_pcr_mask != 0) {
997 log_debug("Configuring public key based PCR policy.");
998
999 /* First: load public key into the TPM */
1000 TPM2B_PUBLIC pubkey_tpm2;
1001 r = openssl_pubkey_to_tpm2_pubkey(pk, &pubkey_tpm2);
1002 if (r < 0)
1003 goto finish;
1004
1005 rc = sym_Esys_LoadExternal(
1006 c,
1007 ESYS_TR_NONE,
1008 ESYS_TR_NONE,
1009 ESYS_TR_NONE,
1010 NULL,
1011 &pubkey_tpm2,
1012 TPM2_RH_OWNER,
1013 &pubkey_handle);
1014 if (rc != TSS2_RC_SUCCESS) {
1015 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1016 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
1017 goto finish;
1018 }
1019
1020 /* Acquire the "name" of what we just loaded */
1021 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
1022 rc = sym_Esys_TR_GetName(
1023 c,
1024 pubkey_handle,
1025 &pubkey_name);
1026 if (rc != TSS2_RC_SUCCESS) {
1027 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1028 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
1029 goto finish;
1030 }
1031
1032 /* Put together the PCR policy we want to use */
1033 TPML_PCR_SELECTION pcr_selection;
1034 tpm2_pcr_mask_to_selection(pubkey_pcr_mask, pcr_bank, &pcr_selection);
1035 rc = sym_Esys_PolicyPCR(
1036 c,
1037 session,
1038 ESYS_TR_NONE,
1039 ESYS_TR_NONE,
1040 ESYS_TR_NONE,
1041 NULL,
1042 &pcr_selection);
1043 if (rc != TSS2_RC_SUCCESS) {
1044 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1045 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
1046 goto finish;
1047 }
1048
1049 /* Get the policy hash of the PCR policy */
1050 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
1051 rc = sym_Esys_PolicyGetDigest(
1052 c,
1053 session,
1054 ESYS_TR_NONE,
1055 ESYS_TR_NONE,
1056 ESYS_TR_NONE,
1057 &approved_policy);
1058 if (rc != TSS2_RC_SUCCESS) {
1059 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1060 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1061 goto finish;
1062 }
1063
1064 /* When we are unlocking and have a signature, let's pass it to the TPM */
1065 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
1066 const TPMT_TK_VERIFIED *check_ticket;
1067 if (signature_json) {
1068 _cleanup_free_ void *signature_raw = NULL;
1069 size_t signature_size;
1070
1071 r = find_signature(
1072 signature_json,
1073 pcr_bank,
1074 pubkey_pcr_mask,
1075 pk,
1076 approved_policy->buffer,
1077 approved_policy->size,
1078 &signature_raw,
1079 &signature_size);
1080 if (r < 0)
1081 goto finish;
1082
1083 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
1084 * hence we need to do the SHA256 part ourselves, first */
1085 TPM2B_DIGEST signature_hash = {
1086 .size = SHA256_DIGEST_SIZE,
1087 };
1088 assert(sizeof(signature_hash.buffer) >= SHA256_DIGEST_SIZE);
1089 sha256_direct(approved_policy->buffer, approved_policy->size, signature_hash.buffer);
1090
1091 TPMT_SIGNATURE policy_signature = {
1092 .sigAlg = TPM2_ALG_RSASSA,
1093 .signature.rsassa = {
1094 .hash = TPM2_ALG_SHA256,
1095 .sig.size = signature_size,
1096 },
1097 };
1098 if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer)) {
1099 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
1100 goto finish;
1101 }
1102 memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
1103
1104 rc = sym_Esys_VerifySignature(
1105 c,
1106 pubkey_handle,
1107 ESYS_TR_NONE,
1108 ESYS_TR_NONE,
1109 ESYS_TR_NONE,
1110 &signature_hash,
1111 &policy_signature,
1112 &check_ticket_buffer);
1113 if (rc != TSS2_RC_SUCCESS) {
1114 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1115 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
1116 goto finish;
1117 }
1118
1119 check_ticket = check_ticket_buffer;
1120 } else {
1121 /* When enrolling, we pass a NULL ticket */
1122 static const TPMT_TK_VERIFIED check_ticket_null = {
1123 .tag = TPM2_ST_VERIFIED,
1124 .hierarchy = TPM2_RH_OWNER,
1125 };
1126
1127 check_ticket = &check_ticket_null;
1128 }
1129
1130 rc = sym_Esys_PolicyAuthorize(
1131 c,
1132 session,
1133 ESYS_TR_NONE,
1134 ESYS_TR_NONE,
1135 ESYS_TR_NONE,
1136 approved_policy,
1137 /* policyRef= */ &(const TPM2B_NONCE) {},
1138 pubkey_name,
1139 check_ticket);
1140 if (rc != TSS2_RC_SUCCESS) {
1141 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1142 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
1143 goto finish;
1144 }
1145 }
1146
1147 if (hash_pcr_mask != 0) {
1148 log_debug("Configuring hash-based PCR policy.");
1149
1150 TPML_PCR_SELECTION pcr_selection;
1151 tpm2_pcr_mask_to_selection(hash_pcr_mask, pcr_bank, &pcr_selection);
1152 rc = sym_Esys_PolicyPCR(
1153 c,
1154 session,
1155 ESYS_TR_NONE,
1156 ESYS_TR_NONE,
1157 ESYS_TR_NONE,
1158 NULL,
1159 &pcr_selection);
1160 if (rc != TSS2_RC_SUCCESS) {
1161 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1162 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
1163 goto finish;
1164 }
1165 }
1166
1167 if (use_pin) {
1168 log_debug("Configuring PIN policy.");
1169
1170 rc = sym_Esys_PolicyAuthValue(
1171 c,
1172 session,
1173 ESYS_TR_NONE,
1174 ESYS_TR_NONE,
1175 ESYS_TR_NONE);
1176 if (rc != TSS2_RC_SUCCESS) {
1177 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1178 "Failed to add authValue policy to TPM: %s",
1179 sym_Tss2_RC_Decode(rc));
1180 goto finish;
1181 }
1182 }
1183
1184 if (DEBUG_LOGGING || ret_policy_digest) {
1185 log_debug("Acquiring policy digest.");
1186
1187 rc = sym_Esys_PolicyGetDigest(
1188 c,
1189 session,
1190 ESYS_TR_NONE,
1191 ESYS_TR_NONE,
1192 ESYS_TR_NONE,
1193 &policy_digest);
1194
1195 if (rc != TSS2_RC_SUCCESS) {
1196 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1197 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1198 goto finish;
1199 }
1200
1201 if (DEBUG_LOGGING) {
1202 _cleanup_free_ char *h = NULL;
1203
1204 h = hexmem(policy_digest->buffer, policy_digest->size);
1205 if (!h) {
1206 r = log_oom();
1207 goto finish;
1208 }
1209
1210 log_debug("Session policy digest: %s", h);
1211 }
1212 }
1213
1214 if (ret_session) {
1215 *ret_session = session;
1216 session = ESYS_TR_NONE;
1217 }
1218
1219 if (ret_policy_digest)
1220 *ret_policy_digest = TAKE_PTR(policy_digest);
1221
1222 if (ret_pcr_bank)
1223 *ret_pcr_bank = pcr_bank;
1224
1225 r = 0;
1226
1227 finish:
1228 session = tpm2_flush_context_verbose(c, session);
1229 pubkey_handle = tpm2_flush_context_verbose(c, pubkey_handle);
1230 return r;
1231 }
1232
1233 int tpm2_seal(const char *device,
1234 uint32_t hash_pcr_mask,
1235 const void *pubkey,
1236 const size_t pubkey_size,
1237 uint32_t pubkey_pcr_mask,
1238 const char *pin,
1239 void **ret_secret,
1240 size_t *ret_secret_size,
1241 void **ret_blob,
1242 size_t *ret_blob_size,
1243 void **ret_pcr_hash,
1244 size_t *ret_pcr_hash_size,
1245 uint16_t *ret_pcr_bank,
1246 uint16_t *ret_primary_alg) {
1247
1248 _cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
1249 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1250 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
1251 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1252 static const TPML_PCR_SELECTION creation_pcr = {};
1253 _cleanup_(erase_and_freep) void *secret = NULL;
1254 _cleanup_free_ void *blob = NULL, *hash = NULL;
1255 TPM2B_SENSITIVE_CREATE hmac_sensitive;
1256 ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE;
1257 TPMI_ALG_PUBLIC primary_alg;
1258 TPM2B_PUBLIC hmac_template;
1259 TPMI_ALG_HASH pcr_bank;
1260 size_t k, blob_size;
1261 usec_t start;
1262 TSS2_RC rc;
1263 int r;
1264
1265 assert(pubkey || pubkey_size == 0);
1266
1267 assert(ret_secret);
1268 assert(ret_secret_size);
1269 assert(ret_blob);
1270 assert(ret_blob_size);
1271 assert(ret_pcr_hash);
1272 assert(ret_pcr_hash_size);
1273 assert(ret_pcr_bank);
1274
1275 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
1276 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
1277
1278 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
1279 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
1280 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
1281 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
1282 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
1283 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
1284 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
1285 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
1286 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
1287 * LUKS2 JSON header.
1288 *
1289 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
1290 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
1291 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
1292 * binding the unlocking to the TPM2 chip. */
1293
1294 start = now(CLOCK_MONOTONIC);
1295
1296 r = tpm2_context_init(device, &c);
1297 if (r < 0)
1298 return r;
1299
1300 r = tpm2_make_primary(c.esys_context, &primary, 0, &primary_alg);
1301 if (r < 0)
1302 return r;
1303
1304 /* we cannot use the bind key before its created */
1305 r = tpm2_make_encryption_session(c.esys_context, primary, ESYS_TR_NONE, NULL, &session);
1306 if (r < 0)
1307 goto finish;
1308
1309 r = tpm2_make_policy_session(
1310 c.esys_context,
1311 primary,
1312 session,
1313 TPM2_SE_TRIAL,
1314 hash_pcr_mask,
1315 /* pcr_bank= */ UINT16_MAX,
1316 pubkey, pubkey_size,
1317 pubkey_pcr_mask,
1318 /* signature_json= */ NULL,
1319 !!pin,
1320 /* ret_session= */ NULL,
1321 &policy_digest,
1322 &pcr_bank);
1323 if (r < 0)
1324 goto finish;
1325
1326 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
1327 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
1328 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
1329 hmac_template = (TPM2B_PUBLIC) {
1330 .size = sizeof(TPMT_PUBLIC),
1331 .publicArea = {
1332 .type = TPM2_ALG_KEYEDHASH,
1333 .nameAlg = TPM2_ALG_SHA256,
1334 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
1335 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
1336 .unique.keyedHash.size = 32,
1337 .authPolicy = *policy_digest,
1338 },
1339 };
1340
1341 hmac_sensitive = (TPM2B_SENSITIVE_CREATE) {
1342 .size = sizeof(hmac_sensitive.sensitive),
1343 .sensitive.data.size = 32,
1344 };
1345 if (pin)
1346 hash_pin(pin, strlen(pin), &hmac_sensitive.sensitive.userAuth);
1347
1348 assert(sizeof(hmac_sensitive.sensitive.data.buffer) >= hmac_sensitive.sensitive.data.size);
1349
1350 (void) tpm2_credit_random(c.esys_context);
1351
1352 log_debug("Generating secret key data.");
1353
1354 r = crypto_random_bytes(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
1355 if (r < 0) {
1356 log_error_errno(r, "Failed to generate secret key: %m");
1357 goto finish;
1358 }
1359
1360 log_debug("Creating HMAC key.");
1361
1362 rc = sym_Esys_Create(
1363 c.esys_context,
1364 primary,
1365 session, /* use HMAC session to enable parameter encryption */
1366 ESYS_TR_NONE,
1367 ESYS_TR_NONE,
1368 &hmac_sensitive,
1369 &hmac_template,
1370 NULL,
1371 &creation_pcr,
1372 &private,
1373 &public,
1374 NULL,
1375 NULL,
1376 NULL);
1377 if (rc != TSS2_RC_SUCCESS) {
1378 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1379 "Failed to generate HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
1380 goto finish;
1381 }
1382
1383 secret = memdup(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
1384 explicit_bzero_safe(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
1385 if (!secret) {
1386 r = log_oom();
1387 goto finish;
1388 }
1389
1390 log_debug("Marshalling private and public part of HMAC key.");
1391
1392 k = ALIGN8(sizeof(*private)) + ALIGN8(sizeof(*public)); /* Some roughly sensible start value */
1393 for (;;) {
1394 _cleanup_free_ void *buf = NULL;
1395 size_t offset = 0;
1396
1397 buf = malloc(k);
1398 if (!buf) {
1399 r = log_oom();
1400 goto finish;
1401 }
1402
1403 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, buf, k, &offset);
1404 if (rc == TSS2_RC_SUCCESS) {
1405 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, buf, k, &offset);
1406 if (rc == TSS2_RC_SUCCESS) {
1407 blob = TAKE_PTR(buf);
1408 blob_size = offset;
1409 break;
1410 }
1411 }
1412 if (rc != TSS2_MU_RC_INSUFFICIENT_BUFFER) {
1413 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1414 "Failed to marshal private/public key: %s", sym_Tss2_RC_Decode(rc));
1415 goto finish;
1416 }
1417
1418 if (k > SIZE_MAX / 2) {
1419 r = log_oom();
1420 goto finish;
1421 }
1422
1423 k *= 2;
1424 }
1425
1426 hash = memdup(policy_digest->buffer, policy_digest->size);
1427 if (!hash)
1428 return log_oom();
1429
1430 if (DEBUG_LOGGING)
1431 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
1432
1433 *ret_secret = TAKE_PTR(secret);
1434 *ret_secret_size = hmac_sensitive.sensitive.data.size;
1435 *ret_blob = TAKE_PTR(blob);
1436 *ret_blob_size = blob_size;
1437 *ret_pcr_hash = TAKE_PTR(hash);
1438 *ret_pcr_hash_size = policy_digest->size;
1439 *ret_pcr_bank = pcr_bank;
1440 *ret_primary_alg = primary_alg;
1441
1442 r = 0;
1443
1444 finish:
1445 explicit_bzero_safe(&hmac_sensitive, sizeof(hmac_sensitive));
1446 primary = tpm2_flush_context_verbose(c.esys_context, primary);
1447 session = tpm2_flush_context_verbose(c.esys_context, session);
1448 return r;
1449 }
1450
1451 int tpm2_unseal(const char *device,
1452 uint32_t hash_pcr_mask,
1453 uint16_t pcr_bank,
1454 const void *pubkey,
1455 size_t pubkey_size,
1456 uint32_t pubkey_pcr_mask,
1457 JsonVariant *signature,
1458 const char *pin,
1459 uint16_t primary_alg,
1460 const void *blob,
1461 size_t blob_size,
1462 const void *known_policy_hash,
1463 size_t known_policy_hash_size,
1464 void **ret_secret,
1465 size_t *ret_secret_size) {
1466
1467 _cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
1468 ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_session = ESYS_TR_NONE,
1469 hmac_key = ESYS_TR_NONE;
1470 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
1471 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1472 _cleanup_(erase_and_freep) char *secret = NULL;
1473 TPM2B_PRIVATE private = {};
1474 TPM2B_PUBLIC public = {};
1475 size_t offset = 0;
1476 TSS2_RC rc;
1477 usec_t start;
1478 int r;
1479
1480 assert(blob);
1481 assert(blob_size > 0);
1482 assert(known_policy_hash_size == 0 || known_policy_hash);
1483 assert(pubkey_size == 0 || pubkey);
1484 assert(ret_secret);
1485 assert(ret_secret_size);
1486
1487 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
1488 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
1489
1490 r = dlopen_tpm2();
1491 if (r < 0)
1492 return log_error_errno(r, "TPM2 support is not installed.");
1493
1494 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
1495 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy
1496 * session. Given we pass the same parameters, this will result in the same "primary" key, and same
1497 * policy hash (the latter of course, only if the PCR values didn't change in between). We unmarshal
1498 * the encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it
1499 * is decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
1500 * and use it to unlock the LUKS2 volume. */
1501
1502 start = now(CLOCK_MONOTONIC);
1503
1504 log_debug("Unmarshalling private part of HMAC key.");
1505
1506 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
1507 if (rc != TSS2_RC_SUCCESS)
1508 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1509 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
1510
1511 log_debug("Unmarshalling public part of HMAC key.");
1512
1513 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
1514 if (rc != TSS2_RC_SUCCESS)
1515 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1516 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
1517
1518 r = tpm2_context_init(device, &c);
1519 if (r < 0)
1520 return r;
1521
1522 r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL);
1523 if (r < 0)
1524 return r;
1525
1526 log_debug("Loading HMAC key into TPM.");
1527
1528 /*
1529 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
1530 * gives you back a different key, the session initiation will fail if a pin
1531 * is provided. If an attacker gives back a bad key, we already lost since
1532 * primary key is not verified and they could attack there as well.
1533 */
1534 rc = sym_Esys_Load(
1535 c.esys_context,
1536 primary,
1537 ESYS_TR_PASSWORD,
1538 ESYS_TR_NONE,
1539 ESYS_TR_NONE,
1540 &private,
1541 &public,
1542 &hmac_key);
1543 if (rc != TSS2_RC_SUCCESS) {
1544 /* If we're in dictionary attack lockout mode, we should see a lockout error here, which we
1545 * need to translate for the caller. */
1546 if (rc == TPM2_RC_LOCKOUT)
1547 r = log_error_errno(
1548 SYNTHETIC_ERRNO(ENOLCK),
1549 "TPM2 device is in dictionary attack lockout mode.");
1550 else
1551 r = log_error_errno(
1552 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1553 "Failed to load HMAC key in TPM: %s",
1554 sym_Tss2_RC_Decode(rc));
1555 goto finish;
1556 }
1557
1558 r = tpm2_make_encryption_session(c.esys_context, primary, hmac_key, pin, &hmac_session);
1559 if (r < 0)
1560 goto finish;
1561
1562 r = tpm2_make_policy_session(
1563 c.esys_context,
1564 primary,
1565 hmac_session,
1566 TPM2_SE_POLICY,
1567 hash_pcr_mask,
1568 pcr_bank,
1569 pubkey, pubkey_size,
1570 pubkey_pcr_mask,
1571 signature,
1572 !!pin,
1573 &session,
1574 &policy_digest,
1575 /* ret_pcr_bank= */ NULL);
1576 if (r < 0)
1577 goto finish;
1578
1579 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
1580 * wait until the TPM2 tells us to go away. */
1581 if (known_policy_hash_size > 0 &&
1582 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
1583 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
1584 "Current policy digest does not match stored policy digest, cancelling "
1585 "TPM2 authentication attempt.");
1586
1587 log_debug("Unsealing HMAC key.");
1588
1589 rc = sym_Esys_Unseal(
1590 c.esys_context,
1591 hmac_key,
1592 session,
1593 hmac_session, /* use HMAC session to enable parameter encryption */
1594 ESYS_TR_NONE,
1595 &unsealed);
1596 if (rc != TSS2_RC_SUCCESS) {
1597 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1598 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
1599 goto finish;
1600 }
1601
1602 secret = memdup(unsealed->buffer, unsealed->size);
1603 explicit_bzero_safe(unsealed->buffer, unsealed->size);
1604 if (!secret) {
1605 r = log_oom();
1606 goto finish;
1607 }
1608
1609 if (DEBUG_LOGGING)
1610 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
1611
1612 *ret_secret = TAKE_PTR(secret);
1613 *ret_secret_size = unsealed->size;
1614
1615 r = 0;
1616
1617 finish:
1618 primary = tpm2_flush_context_verbose(c.esys_context, primary);
1619 session = tpm2_flush_context_verbose(c.esys_context, session);
1620 hmac_key = tpm2_flush_context_verbose(c.esys_context, hmac_key);
1621 return r;
1622 }
1623
1624 #endif
1625
1626 int tpm2_list_devices(void) {
1627 #if HAVE_TPM2
1628 _cleanup_(table_unrefp) Table *t = NULL;
1629 _cleanup_(closedirp) DIR *d = NULL;
1630 int r;
1631
1632 r = dlopen_tpm2();
1633 if (r < 0)
1634 return log_error_errno(r, "TPM2 support is not installed.");
1635
1636 t = table_new("path", "device", "driver");
1637 if (!t)
1638 return log_oom();
1639
1640 d = opendir("/sys/class/tpmrm");
1641 if (!d) {
1642 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
1643 if (errno != ENOENT)
1644 return -errno;
1645 } else {
1646 for (;;) {
1647 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
1648 struct dirent *de;
1649
1650 de = readdir_no_dot(d);
1651 if (!de)
1652 break;
1653
1654 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
1655 if (!device_path)
1656 return log_oom();
1657
1658 r = readlink_malloc(device_path, &device);
1659 if (r < 0)
1660 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
1661 else {
1662 driver_path = path_join(device_path, "driver");
1663 if (!driver_path)
1664 return log_oom();
1665
1666 r = readlink_malloc(driver_path, &driver);
1667 if (r < 0)
1668 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
1669 }
1670
1671 node = path_join("/dev", de->d_name);
1672 if (!node)
1673 return log_oom();
1674
1675 r = table_add_many(
1676 t,
1677 TABLE_PATH, node,
1678 TABLE_STRING, device ? last_path_component(device) : NULL,
1679 TABLE_STRING, driver ? last_path_component(driver) : NULL);
1680 if (r < 0)
1681 return table_log_add_error(r);
1682 }
1683 }
1684
1685 if (table_get_rows(t) <= 1) {
1686 log_info("No suitable TPM2 devices found.");
1687 return 0;
1688 }
1689
1690 r = table_print(t, stdout);
1691 if (r < 0)
1692 return log_error_errno(r, "Failed to show device table: %m");
1693
1694 return 0;
1695 #else
1696 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1697 "TPM2 not supported on this build.");
1698 #endif
1699 }
1700
1701 int tpm2_find_device_auto(
1702 int log_level, /* log level when no device is found */
1703 char **ret) {
1704 #if HAVE_TPM2
1705 _cleanup_(closedirp) DIR *d = NULL;
1706 int r;
1707
1708 r = dlopen_tpm2();
1709 if (r < 0)
1710 return log_error_errno(r, "TPM2 support is not installed.");
1711
1712 d = opendir("/sys/class/tpmrm");
1713 if (!d) {
1714 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
1715 "Failed to open /sys/class/tpmrm: %m");
1716 if (errno != ENOENT)
1717 return -errno;
1718 } else {
1719 _cleanup_free_ char *node = NULL;
1720
1721 for (;;) {
1722 struct dirent *de;
1723
1724 de = readdir_no_dot(d);
1725 if (!de)
1726 break;
1727
1728 if (node)
1729 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
1730 "More than one TPM2 (tpmrm) device found.");
1731
1732 node = path_join("/dev", de->d_name);
1733 if (!node)
1734 return log_oom();
1735 }
1736
1737 if (node) {
1738 *ret = TAKE_PTR(node);
1739 return 0;
1740 }
1741 }
1742
1743 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
1744 #else
1745 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1746 "TPM2 not supported on this build.");
1747 #endif
1748 }
1749
1750 int tpm2_parse_pcrs(const char *s, uint32_t *ret) {
1751 const char *p = ASSERT_PTR(s);
1752 uint32_t mask = 0;
1753 int r;
1754
1755 if (isempty(s)) {
1756 *ret = 0;
1757 return 0;
1758 }
1759
1760 /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
1761 * and most other tools expect comma separated PCR specifications. We also support "+" since in
1762 * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
1763 * avoid escaping. */
1764
1765 for (;;) {
1766 _cleanup_free_ char *pcr = NULL;
1767 unsigned n;
1768
1769 r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
1770 if (r == 0)
1771 break;
1772 if (r < 0)
1773 return log_error_errno(r, "Failed to parse PCR list: %s", s);
1774
1775 r = safe_atou(pcr, &n);
1776 if (r < 0)
1777 return log_error_errno(r, "Failed to parse PCR number: %s", pcr);
1778 if (n >= TPM2_PCRS_MAX)
1779 return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
1780 "PCR number out of range (valid range 0…23): %u", n);
1781
1782 mask |= UINT32_C(1) << n;
1783 }
1784
1785 *ret = mask;
1786 return 0;
1787 }
1788
1789 int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
1790 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
1791 JsonVariant* pcr_array[TPM2_PCRS_MAX];
1792 unsigned n_pcrs = 0;
1793 int r;
1794
1795 for (size_t i = 0; i < ELEMENTSOF(pcr_array); i++) {
1796 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
1797 continue;
1798
1799 r = json_variant_new_integer(pcr_array + n_pcrs, i);
1800 if (r < 0)
1801 goto finish;
1802
1803 n_pcrs++;
1804 }
1805
1806 r = json_variant_new_array(&a, pcr_array, n_pcrs);
1807 if (r < 0)
1808 goto finish;
1809
1810 if (ret)
1811 *ret = TAKE_PTR(a);
1812 r = 0;
1813
1814 finish:
1815 json_variant_unref_many(pcr_array, n_pcrs);
1816 return r;
1817 }
1818
1819 int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
1820 JsonVariant *e;
1821 uint32_t mask = 0;
1822
1823 if (!json_variant_is_array(v))
1824 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
1825
1826 JSON_VARIANT_ARRAY_FOREACH(e, v) {
1827 uint64_t u;
1828
1829 if (!json_variant_is_unsigned(e))
1830 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
1831
1832 u = json_variant_unsigned(e);
1833 if (u >= TPM2_PCRS_MAX)
1834 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
1835
1836 mask |= UINT32_C(1) << u;
1837 }
1838
1839 if (ret)
1840 *ret = mask;
1841
1842 return 0;
1843 }
1844
1845 int tpm2_make_luks2_json(
1846 int keyslot,
1847 uint32_t hash_pcr_mask,
1848 uint16_t pcr_bank,
1849 const void *pubkey,
1850 size_t pubkey_size,
1851 uint32_t pubkey_pcr_mask,
1852 uint16_t primary_alg,
1853 const void *blob,
1854 size_t blob_size,
1855 const void *policy_hash,
1856 size_t policy_hash_size,
1857 TPM2Flags flags,
1858 JsonVariant **ret) {
1859
1860 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
1861 _cleanup_free_ char *keyslot_as_string = NULL;
1862 int r;
1863
1864 assert(blob || blob_size == 0);
1865 assert(policy_hash || policy_hash_size == 0);
1866 assert(pubkey || pubkey_size == 0);
1867
1868 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
1869 return -ENOMEM;
1870
1871 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
1872 if (r < 0)
1873 return r;
1874
1875 if (pubkey_pcr_mask != 0) {
1876 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
1877 if (r < 0)
1878 return r;
1879 }
1880
1881 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
1882 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
1883 * object should use "_" rather than "-" in field names. */
1884
1885 r = json_build(&v,
1886 JSON_BUILD_OBJECT(
1887 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
1888 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
1889 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
1890 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
1891 JSON_BUILD_PAIR_CONDITION(!!tpm2_pcr_bank_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_pcr_bank_to_string(pcr_bank))),
1892 JSON_BUILD_PAIR_CONDITION(!!tpm2_primary_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_primary_alg_to_string(primary_alg))),
1893 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
1894 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
1895 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
1896 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size))));
1897 if (r < 0)
1898 return r;
1899
1900 if (ret)
1901 *ret = TAKE_PTR(v);
1902
1903 return keyslot;
1904 }
1905
1906 int tpm2_parse_luks2_json(
1907 JsonVariant *v,
1908 int *ret_keyslot,
1909 uint32_t *ret_hash_pcr_mask,
1910 uint16_t *ret_pcr_bank,
1911 void **ret_pubkey,
1912 size_t *ret_pubkey_size,
1913 uint32_t *ret_pubkey_pcr_mask,
1914 uint16_t *ret_primary_alg,
1915 void **ret_blob,
1916 size_t *ret_blob_size,
1917 void **ret_policy_hash,
1918 size_t *ret_policy_hash_size,
1919 TPM2Flags *ret_flags) {
1920
1921 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL;
1922 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0;
1923 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
1924 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
1925 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
1926 int r, keyslot = -1;
1927 TPM2Flags flags = 0;
1928 JsonVariant *w;
1929
1930 assert(v);
1931
1932 if (ret_keyslot) {
1933 keyslot = cryptsetup_get_keyslot_from_token(v);
1934 if (keyslot < 0) {
1935 /* Return a recognizable error when parsing this field, so that callers can handle parsing
1936 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
1937 * spec */
1938 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
1939 return -EUCLEAN;
1940 }
1941 }
1942
1943 w = json_variant_by_key(v, "tpm2-pcrs");
1944 if (!w)
1945 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
1946
1947 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
1948 if (r < 0)
1949 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
1950
1951 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
1952 * to SHA256. */
1953 w = json_variant_by_key(v, "tpm2-pcr-bank");
1954 if (w) {
1955 /* The PCR bank field is optional */
1956
1957 if (!json_variant_is_string(w))
1958 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
1959
1960 r = tpm2_pcr_bank_from_string(json_variant_string(w));
1961 if (r < 0)
1962 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
1963
1964 pcr_bank = r;
1965 }
1966
1967 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
1968 * the algorithm was hardcoded to ECC. */
1969 w = json_variant_by_key(v, "tpm2-primary-alg");
1970 if (w) {
1971 /* The primary key algorithm is optional */
1972
1973 if (!json_variant_is_string(w))
1974 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
1975
1976 r = tpm2_primary_alg_from_string(json_variant_string(w));
1977 if (r < 0)
1978 return log_debug_errno(r, "TPM2 primary key algorithm invalid or not supported: %s", json_variant_string(w));
1979
1980 primary_alg = r;
1981 }
1982
1983 w = json_variant_by_key(v, "tpm2-blob");
1984 if (!w)
1985 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
1986
1987 r = json_variant_unbase64(w, &blob, &blob_size);
1988 if (r < 0)
1989 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
1990
1991 w = json_variant_by_key(v, "tpm2-policy-hash");
1992 if (!w)
1993 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
1994
1995 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
1996 if (r < 0)
1997 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
1998
1999 w = json_variant_by_key(v, "tpm2-pin");
2000 if (w) {
2001 if (!json_variant_is_boolean(w))
2002 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
2003
2004 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
2005 }
2006
2007 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
2008 if (w) {
2009 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
2010 if (r < 0)
2011 return r;
2012 }
2013
2014 w = json_variant_by_key(v, "tpm2_pubkey");
2015 if (w) {
2016 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
2017 if (r < 0)
2018 return log_debug_errno(r, "Failed to decode PCR public key.");
2019 } else if (pubkey_pcr_mask != 0)
2020 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
2021
2022 if (ret_keyslot)
2023 *ret_keyslot = keyslot;
2024 if (ret_hash_pcr_mask)
2025 *ret_hash_pcr_mask = hash_pcr_mask;
2026 if (ret_pcr_bank)
2027 *ret_pcr_bank = pcr_bank;
2028 if (ret_pubkey)
2029 *ret_pubkey = TAKE_PTR(pubkey);
2030 if (ret_pubkey_size)
2031 *ret_pubkey_size = pubkey_size;
2032 if (ret_pubkey_pcr_mask)
2033 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
2034 if (ret_primary_alg)
2035 *ret_primary_alg = primary_alg;
2036 if (ret_blob)
2037 *ret_blob = TAKE_PTR(blob);
2038 if (ret_blob_size)
2039 *ret_blob_size = blob_size;
2040 if (ret_policy_hash)
2041 *ret_policy_hash = TAKE_PTR(policy_hash);
2042 if (ret_policy_hash_size)
2043 *ret_policy_hash_size = policy_hash_size;
2044 if (ret_flags)
2045 *ret_flags = flags;
2046
2047 return 0;
2048 }
2049
2050 const char *tpm2_pcr_bank_to_string(uint16_t bank) {
2051 if (bank == TPM2_ALG_SHA1)
2052 return "sha1";
2053 if (bank == TPM2_ALG_SHA256)
2054 return "sha256";
2055 if (bank == TPM2_ALG_SHA384)
2056 return "sha384";
2057 if (bank == TPM2_ALG_SHA512)
2058 return "sha512";
2059 return NULL;
2060 }
2061
2062 int tpm2_pcr_bank_from_string(const char *bank) {
2063 if (strcaseeq_ptr(bank, "sha1"))
2064 return TPM2_ALG_SHA1;
2065 if (strcaseeq_ptr(bank, "sha256"))
2066 return TPM2_ALG_SHA256;
2067 if (strcaseeq_ptr(bank, "sha384"))
2068 return TPM2_ALG_SHA384;
2069 if (strcaseeq_ptr(bank, "sha512"))
2070 return TPM2_ALG_SHA512;
2071 return -EINVAL;
2072 }
2073
2074 const char *tpm2_primary_alg_to_string(uint16_t alg) {
2075 if (alg == TPM2_ALG_ECC)
2076 return "ecc";
2077 if (alg == TPM2_ALG_RSA)
2078 return "rsa";
2079 return NULL;
2080 }
2081
2082 int tpm2_primary_alg_from_string(const char *alg) {
2083 if (strcaseeq_ptr(alg, "ecc"))
2084 return TPM2_ALG_ECC;
2085 if (strcaseeq_ptr(alg, "rsa"))
2086 return TPM2_ALG_RSA;
2087 return -EINVAL;
2088 }
2089
2090 Tpm2Support tpm2_support(void) {
2091 Tpm2Support support = TPM2_SUPPORT_NONE;
2092 int r;
2093
2094 if (detect_container() <= 0) {
2095 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
2096 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
2097 * let's assume containers never have a TPM, at least for now. */
2098
2099 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
2100 if (r < 0) {
2101 if (r != -ENOENT)
2102 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
2103 } else if (r == 0) /* populated! */
2104 support |= TPM2_SUPPORT_DRIVER;
2105 }
2106
2107 if (efi_has_tpm2())
2108 support |= TPM2_SUPPORT_FIRMWARE;
2109
2110 #if HAVE_TPM2
2111 support |= TPM2_SUPPORT_SYSTEM;
2112 #endif
2113
2114 return support;
2115 }
2116
2117 int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask) {
2118 uint32_t m;
2119 int r;
2120
2121 assert(mask);
2122
2123 /* For use in getopt_long() command line parsers: merges masks specified on the command line */
2124
2125 if (isempty(arg)) {
2126 *mask = 0;
2127 return 0;
2128 }
2129
2130 r = tpm2_parse_pcrs(arg, &m);
2131 if (r < 0)
2132 return r;
2133
2134 if (*mask == UINT32_MAX)
2135 *mask = m;
2136 else
2137 *mask |= m;
2138
2139 return 0;
2140 }
2141
2142 int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
2143 _cleanup_free_ char *discovered_path = NULL;
2144 _cleanup_fclose_ FILE *f = NULL;
2145 int r;
2146
2147 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
2148 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
2149
2150 if (!path)
2151 path = "tpm2-pcr-signature.json";
2152
2153 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
2154 if (r < 0)
2155 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
2156
2157 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
2158 if (r < 0)
2159 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
2160
2161 return 0;
2162 }
2163
2164 int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
2165 _cleanup_free_ char *discovered_path = NULL;
2166 _cleanup_fclose_ FILE *f = NULL;
2167 int r;
2168
2169 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
2170 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
2171
2172 if (!path)
2173 path = "tpm2-pcr-public-key.pem";
2174
2175 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
2176 if (r < 0)
2177 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
2178
2179 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
2180 if (r < 0)
2181 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
2182
2183 return 0;
2184 }
2185
2186 int pcr_mask_to_string(uint32_t mask, char **ret) {
2187 _cleanup_free_ char *buf = NULL;
2188 int r;
2189
2190 assert(ret);
2191
2192 for (unsigned i = 0; i < TPM2_PCRS_MAX; i++) {
2193 if (!(mask & (UINT32_C(1) << i)))
2194 continue;
2195
2196 r = strextendf_with_separator(&buf, "+", "%u", i);
2197 if (r < 0)
2198 return r;
2199 }
2200
2201 *ret = TAKE_PTR(buf);
2202 return 0;
2203 }