]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/tpm2-util.c
Merge pull request #24263 from pothos/sysext-for-static-binaries
[thirdparty/systemd.git] / src / shared / tpm2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "efi-api.h"
4 #include "extract-word.h"
5 #include "parse-util.h"
6 #include "stat-util.h"
7 #include "tpm2-util.h"
8 #include "virt.h"
9
10 #if HAVE_TPM2
11 #include "alloc-util.h"
12 #include "dirent-util.h"
13 #include "dlfcn-util.h"
14 #include "fd-util.h"
15 #include "format-table.h"
16 #include "fs-util.h"
17 #include "hexdecoct.h"
18 #include "memory-util.h"
19 #include "random-util.h"
20 #include "sha256.h"
21 #include "time-util.h"
22
23 static void *libtss2_esys_dl = NULL;
24 static void *libtss2_rc_dl = NULL;
25 static void *libtss2_mu_dl = NULL;
26
27 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;
28 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;
29 void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
30 TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
31 void (*sym_Esys_Free)(void *ptr) = NULL;
32 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);
33 TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
34 TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
35 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;
36 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);
37 TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
38 TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
39 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;
40 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;
41 TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
42 TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask);
43 TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
44 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;
45
46 const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
47
48 TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
49 TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
50 TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
51 TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
52
53 int dlopen_tpm2(void) {
54 int r;
55
56 r = dlopen_many_sym_or_warn(
57 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
58 DLSYM_ARG(Esys_Create),
59 DLSYM_ARG(Esys_CreatePrimary),
60 DLSYM_ARG(Esys_Finalize),
61 DLSYM_ARG(Esys_FlushContext),
62 DLSYM_ARG(Esys_Free),
63 DLSYM_ARG(Esys_GetCapability),
64 DLSYM_ARG(Esys_GetRandom),
65 DLSYM_ARG(Esys_Initialize),
66 DLSYM_ARG(Esys_Load),
67 DLSYM_ARG(Esys_PCR_Read),
68 DLSYM_ARG(Esys_PolicyAuthValue),
69 DLSYM_ARG(Esys_PolicyGetDigest),
70 DLSYM_ARG(Esys_PolicyPCR),
71 DLSYM_ARG(Esys_StartAuthSession),
72 DLSYM_ARG(Esys_Startup),
73 DLSYM_ARG(Esys_TRSess_SetAttributes),
74 DLSYM_ARG(Esys_TR_SetAuth),
75 DLSYM_ARG(Esys_Unseal));
76 if (r < 0)
77 return r;
78
79 r = dlopen_many_sym_or_warn(
80 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
81 DLSYM_ARG(Tss2_RC_Decode));
82 if (r < 0)
83 return r;
84
85 return dlopen_many_sym_or_warn(
86 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
87 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
88 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
89 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
90 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal));
91 }
92
93 struct tpm2_context {
94 ESYS_CONTEXT *esys_context;
95 void *tcti_dl;
96 TSS2_TCTI_CONTEXT *tcti_context;
97 };
98
99 static void tpm2_context_destroy(struct tpm2_context *c) {
100 assert(c);
101
102 if (c->esys_context)
103 sym_Esys_Finalize(&c->esys_context);
104
105 c->tcti_context = mfree(c->tcti_context);
106
107 if (c->tcti_dl) {
108 dlclose(c->tcti_dl);
109 c->tcti_dl = NULL;
110 }
111 }
112
113 static inline void Esys_Finalize_wrapper(ESYS_CONTEXT **c) {
114 /* A wrapper around Esys_Finalize() for use with _cleanup_(). Only reasons we need this wrapper is
115 * because the function itself warn logs if we'd pass a pointer to NULL, and we don't want that. */
116 if (*c)
117 sym_Esys_Finalize(c);
118 }
119
120 static inline void Esys_Freep(void *p) {
121 if (*(void**) p)
122 sym_Esys_Free(*(void**) p);
123 }
124
125 static ESYS_TR flush_context_verbose(ESYS_CONTEXT *c, ESYS_TR handle) {
126 TSS2_RC rc;
127
128 if (!c || handle == ESYS_TR_NONE)
129 return ESYS_TR_NONE;
130
131 rc = sym_Esys_FlushContext(c, handle);
132 if (rc != TSS2_RC_SUCCESS) /* We ignore failures here (besides debug logging), since this is called
133 * in error paths, where we cannot do anything about failures anymore. And
134 * when it is called in successful codepaths by this time we already did
135 * what we wanted to do, and got the results we wanted so there's no
136 * reason to make this fail more loudly than necessary. */
137 log_debug("Failed to get flush context of TPM, ignoring: %s", sym_Tss2_RC_Decode(rc));
138
139 return ESYS_TR_NONE;
140 }
141
142 static int tpm2_init(const char *device, struct tpm2_context *ret) {
143 _cleanup_(Esys_Finalize_wrapper) ESYS_CONTEXT *c = NULL;
144 _cleanup_free_ TSS2_TCTI_CONTEXT *tcti = NULL;
145 _cleanup_(dlclosep) void *dl = NULL;
146 TSS2_RC rc;
147 int r;
148
149 r = dlopen_tpm2();
150 if (r < 0)
151 return log_error_errno(r, "TPM2 support not installed: %m");
152
153 if (!device)
154 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
155
156 if (device) {
157 const char *param, *driver, *fn;
158 const TSS2_TCTI_INFO* info;
159 TSS2_TCTI_INFO_FUNC func;
160 size_t sz = 0;
161
162 param = strchr(device, ':');
163 if (param) {
164 driver = strndupa_safe(device, param - device);
165 param++;
166 } else {
167 driver = "device";
168 param = device;
169 }
170
171 fn = strjoina("libtss2-tcti-", driver, ".so.0");
172
173 dl = dlopen(fn, RTLD_NOW);
174 if (!dl)
175 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
176
177 func = dlsym(dl, TSS2_TCTI_INFO_SYMBOL);
178 if (!func)
179 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
180 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
181 dlerror());
182
183 info = func();
184 if (!info)
185 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
186
187
188 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
189
190 rc = info->init(NULL, &sz, NULL);
191 if (rc != TPM2_RC_SUCCESS)
192 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
193 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
194
195 tcti = malloc0(sz);
196 if (!tcti)
197 return log_oom();
198
199 rc = info->init(tcti, &sz, param);
200 if (rc != TPM2_RC_SUCCESS)
201 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
202 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
203 }
204
205 rc = sym_Esys_Initialize(&c, tcti, NULL);
206 if (rc != TSS2_RC_SUCCESS)
207 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
208 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
209
210 rc = sym_Esys_Startup(c, TPM2_SU_CLEAR);
211 if (rc == TPM2_RC_INITIALIZE)
212 log_debug("TPM already started up.");
213 else if (rc == TSS2_RC_SUCCESS)
214 log_debug("TPM successfully started up.");
215 else
216 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
217 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
218
219 *ret = (struct tpm2_context) {
220 .esys_context = TAKE_PTR(c),
221 .tcti_context = TAKE_PTR(tcti),
222 .tcti_dl = TAKE_PTR(dl),
223 };
224
225 return 0;
226 }
227
228 static int tpm2_credit_random(ESYS_CONTEXT *c) {
229 size_t rps, done = 0;
230 TSS2_RC rc;
231 int r;
232
233 assert(c);
234
235 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
236 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
237 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
238 * any entropy. */
239
240 for (rps = random_pool_size(); rps > 0;) {
241 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
242
243 rc = sym_Esys_GetRandom(
244 c,
245 ESYS_TR_NONE,
246 ESYS_TR_NONE,
247 ESYS_TR_NONE,
248 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
249 &buffer);
250 if (rc != TSS2_RC_SUCCESS)
251 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
252 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
253
254 if (buffer->size == 0)
255 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
256 "Zero-sized entropy returned from TPM.");
257
258 r = random_write_entropy(-1, buffer->buffer, buffer->size, false);
259 if (r < 0)
260 return log_error_errno(r, "Failed wo write entropy to kernel: %m");
261
262 done += buffer->size;
263 rps = LESS_BY(rps, buffer->size);
264 }
265
266 log_debug("Added %zu bytes of entropy to the kernel random pool.", done);
267 return 0;
268 }
269
270 static int tpm2_make_primary(
271 ESYS_CONTEXT *c,
272 ESYS_TR *ret_primary,
273 TPMI_ALG_PUBLIC alg,
274 TPMI_ALG_PUBLIC *ret_alg) {
275
276 static const TPM2B_SENSITIVE_CREATE primary_sensitive = {};
277 static const TPM2B_PUBLIC primary_template_ecc = {
278 .size = sizeof(TPMT_PUBLIC),
279 .publicArea = {
280 .type = TPM2_ALG_ECC,
281 .nameAlg = TPM2_ALG_SHA256,
282 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
283 .parameters.eccDetail = {
284 .symmetric = {
285 .algorithm = TPM2_ALG_AES,
286 .keyBits.aes = 128,
287 .mode.aes = TPM2_ALG_CFB,
288 },
289 .scheme.scheme = TPM2_ALG_NULL,
290 .curveID = TPM2_ECC_NIST_P256,
291 .kdf.scheme = TPM2_ALG_NULL,
292 },
293 },
294 };
295 static const TPM2B_PUBLIC primary_template_rsa = {
296 .size = sizeof(TPMT_PUBLIC),
297 .publicArea = {
298 .type = TPM2_ALG_RSA,
299 .nameAlg = TPM2_ALG_SHA256,
300 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
301 .parameters.rsaDetail = {
302 .symmetric = {
303 .algorithm = TPM2_ALG_AES,
304 .keyBits.aes = 128,
305 .mode.aes = TPM2_ALG_CFB,
306 },
307 .scheme.scheme = TPM2_ALG_NULL,
308 .keyBits = 2048,
309 },
310 },
311 };
312
313 static const TPML_PCR_SELECTION creation_pcr = {};
314 ESYS_TR primary = ESYS_TR_NONE;
315 TSS2_RC rc;
316 usec_t ts;
317
318 log_debug("Creating primary key on TPM.");
319
320 /* So apparently not all TPM2 devices support ECC. ECC is generally preferably, because it's so much
321 * faster, noticeably so (~10s vs. ~240ms on my system). Hence, unless explicitly configured let's
322 * try to use ECC first, and if that does not work, let's fall back to RSA. */
323
324 ts = now(CLOCK_MONOTONIC);
325
326 if (IN_SET(alg, 0, TPM2_ALG_ECC)) {
327 rc = sym_Esys_CreatePrimary(
328 c,
329 ESYS_TR_RH_OWNER,
330 ESYS_TR_PASSWORD,
331 ESYS_TR_NONE,
332 ESYS_TR_NONE,
333 &primary_sensitive,
334 &primary_template_ecc,
335 NULL,
336 &creation_pcr,
337 &primary,
338 NULL,
339 NULL,
340 NULL,
341 NULL);
342
343 if (rc != TSS2_RC_SUCCESS) {
344 if (alg != 0)
345 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
346 "Failed to generate ECC primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
347
348 log_debug("Failed to generate ECC primary key in TPM, trying RSA: %s", sym_Tss2_RC_Decode(rc));
349 } else {
350 log_debug("Successfully created ECC primary key on TPM.");
351 alg = TPM2_ALG_ECC;
352 }
353 }
354
355 if (IN_SET(alg, 0, TPM2_ALG_RSA)) {
356 rc = sym_Esys_CreatePrimary(
357 c,
358 ESYS_TR_RH_OWNER,
359 ESYS_TR_PASSWORD,
360 ESYS_TR_NONE,
361 ESYS_TR_NONE,
362 &primary_sensitive,
363 &primary_template_rsa,
364 NULL,
365 &creation_pcr,
366 &primary,
367 NULL,
368 NULL,
369 NULL,
370 NULL);
371 if (rc != TSS2_RC_SUCCESS)
372 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
373 "Failed to generate RSA primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
374 else if (alg == 0) {
375 log_notice("TPM2 chip apparently does not support ECC primary keys, falling back to RSA. "
376 "This likely means TPM2 operations will be relatively slow, please be patient.");
377 alg = TPM2_ALG_RSA;
378 }
379
380 log_debug("Successfully created RSA primary key on TPM.");
381 }
382
383 log_debug("Generating primary key on TPM2 took %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
384
385 *ret_primary = primary;
386 if (ret_alg)
387 *ret_alg = alg;
388
389 return 0;
390 }
391
392 static void tpm2_pcr_mask_to_selecion(uint32_t mask, uint16_t bank, TPML_PCR_SELECTION *ret) {
393 assert(ret);
394
395 /* We only do 24bit here, as that's what PC TPMs are supposed to support */
396 assert(mask <= 0xFFFFFFU);
397
398 *ret = (TPML_PCR_SELECTION) {
399 .count = 1,
400 .pcrSelections[0].hash = bank,
401 .pcrSelections[0].sizeofSelect = 3,
402 .pcrSelections[0].pcrSelect[0] = mask & 0xFF,
403 .pcrSelections[0].pcrSelect[1] = (mask >> 8) & 0xFF,
404 .pcrSelections[0].pcrSelect[2] = (mask >> 16) & 0xFF,
405 };
406 }
407
408 static unsigned find_nth_bit(uint32_t mask, unsigned n) {
409 uint32_t bit = 1;
410
411 assert(n < 32);
412
413 /* Returns the bit index of the nth set bit, e.g. mask=0b101001, n=3 → 5 */
414
415 for (unsigned i = 0; i < sizeof(mask)*8; i++) {
416
417 if (bit & mask) {
418 if (n == 0)
419 return i;
420
421 n--;
422 }
423
424 bit <<= 1;
425 }
426
427 return UINT_MAX;
428 }
429
430 static int tpm2_pcr_mask_good(
431 ESYS_CONTEXT *c,
432 TPMI_ALG_HASH bank,
433 uint32_t mask) {
434
435 _cleanup_(Esys_Freep) TPML_DIGEST *pcr_values = NULL;
436 TPML_PCR_SELECTION selection;
437 bool good = false;
438 TSS2_RC rc;
439
440 assert(c);
441
442 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
443 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
444 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
445
446 tpm2_pcr_mask_to_selecion(mask, bank, &selection);
447
448 rc = sym_Esys_PCR_Read(
449 c,
450 ESYS_TR_NONE,
451 ESYS_TR_NONE,
452 ESYS_TR_NONE,
453 &selection,
454 NULL,
455 NULL,
456 &pcr_values);
457 if (rc != TSS2_RC_SUCCESS)
458 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
459 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
460
461 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
462 for (unsigned i = 0; i < pcr_values->count; i++) {
463 if (DEBUG_LOGGING) {
464 _cleanup_free_ char *h = NULL;
465 unsigned j;
466
467 h = hexmem(pcr_values->digests[i].buffer, pcr_values->digests[i].size);
468 j = find_nth_bit(mask, i);
469 assert(j != UINT_MAX);
470
471 log_debug("PCR %u value: %s", j, strna(h));
472 }
473
474 if (!memeqbyte(0x00, pcr_values->digests[i].buffer, pcr_values->digests[i].size) &&
475 !memeqbyte(0xFF, pcr_values->digests[i].buffer, pcr_values->digests[i].size))
476 good = true;
477 }
478
479 return good;
480 }
481
482 static int tpm2_get_best_pcr_bank(
483 ESYS_CONTEXT *c,
484 uint32_t pcr_mask,
485 TPMI_ALG_HASH *ret) {
486
487 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
488 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
489 TPMI_YES_NO more;
490 TSS2_RC rc;
491
492 assert(c);
493
494 rc = sym_Esys_GetCapability(
495 c,
496 ESYS_TR_NONE,
497 ESYS_TR_NONE,
498 ESYS_TR_NONE,
499 TPM2_CAP_PCRS,
500 0,
501 1,
502 &more,
503 &pcap);
504 if (rc != TSS2_RC_SUCCESS)
505 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
506 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
507
508 assert(pcap->capability == TPM2_CAP_PCRS);
509
510 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
511 bool valid = true;
512 int good;
513
514 /* For now we are only interested in the SHA1 and SHA256 banks */
515 if (!IN_SET(pcap->data.assignedPCR.pcrSelections[i].hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
516 continue;
517
518 /* As per
519 * https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
520 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over
521 * it. */
522 if (pcap->data.assignedPCR.pcrSelections[i].sizeofSelect < TPM2_PCRS_MAX/8) {
523 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
524 strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash)));
525 continue;
526 }
527
528 assert_cc(TPM2_PCRS_MAX % 8 == 0);
529
530 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
531 * enabled for this bank. Otherwise this TPM doesn't qualify. */
532 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
533 if (pcap->data.assignedPCR.pcrSelections[i].pcrSelect[j] != 0xFF) {
534 valid = false;
535 break;
536 }
537
538 if (!valid) {
539 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
540 strna(tpm2_pcr_bank_to_string(pcap->data.assignedPCR.pcrSelections[i].hash)));
541 continue;
542 }
543
544 good = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
545 if (good < 0)
546 return good;
547
548 if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) {
549 supported_hash = TPM2_ALG_SHA256;
550 if (good) {
551 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
552 hash_with_valid_pcr = TPM2_ALG_SHA256;
553 break;
554 }
555 } else {
556 assert(pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1);
557
558 if (supported_hash == 0)
559 supported_hash = TPM2_ALG_SHA1;
560
561 if (good && hash_with_valid_pcr == 0)
562 hash_with_valid_pcr = TPM2_ALG_SHA1;
563 }
564 }
565
566 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
567 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
568 * SHA1.
569 *
570 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
571 * not initialized. */
572
573 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
574 assert(supported_hash == TPM2_ALG_SHA256);
575 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
576 *ret = TPM2_ALG_SHA256;
577 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
578 if (supported_hash == TPM2_ALG_SHA256)
579 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.");
580 else {
581 assert(supported_hash == TPM2_ALG_SHA1);
582 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.");
583 }
584
585 *ret = TPM2_ALG_SHA1;
586 } else if (supported_hash == TPM2_ALG_SHA256) {
587 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!");
588 *ret = TPM2_ALG_SHA256;
589 } else if (supported_hash == TPM2_ALG_SHA1) {
590 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!");
591 *ret = TPM2_ALG_SHA1;
592 } else
593 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
594 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
595
596 return 0;
597 }
598
599 static int tpm2_make_encryption_session(
600 ESYS_CONTEXT *c,
601 ESYS_TR primary,
602 ESYS_TR *ret_session) {
603
604 static const TPMT_SYM_DEF symmetric = {
605 .algorithm = TPM2_ALG_AES,
606 .keyBits = {
607 .aes = 128,
608 },
609 .mode = {
610 .aes = TPM2_ALG_CFB,
611 },
612 };
613 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
614 TPMA_SESSION_CONTINUESESSION;
615 ESYS_TR session = ESYS_TR_NONE;
616 TSS2_RC rc;
617
618 assert(c);
619
620 log_debug("Starting HMAC encryption session.");
621
622 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
623 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
624 * recover the salt, which is then used for key derivation. */
625 rc = sym_Esys_StartAuthSession(
626 c,
627 primary,
628 ESYS_TR_NONE,
629 ESYS_TR_NONE,
630 ESYS_TR_NONE,
631 ESYS_TR_NONE,
632 NULL,
633 TPM2_SE_HMAC,
634 &symmetric,
635 TPM2_ALG_SHA256,
636 &session);
637 if (rc != TSS2_RC_SUCCESS)
638 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
639 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
640
641 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
642 * always used for sessions), this provides confidentiality, integrity and replay protection for
643 * operations that use this session. */
644 rc = sym_Esys_TRSess_SetAttributes(c, session, sessionAttributes, 0xff);
645 if (rc != TSS2_RC_SUCCESS)
646 return log_error_errno(
647 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
648 "Failed to configure TPM session: %s",
649 sym_Tss2_RC_Decode(rc));
650
651 if (ret_session) {
652 *ret_session = session;
653 session = ESYS_TR_NONE;
654 }
655
656 session = flush_context_verbose(c, session);
657 return 0;
658 }
659
660 static int tpm2_make_pcr_session(
661 ESYS_CONTEXT *c,
662 ESYS_TR primary,
663 ESYS_TR parent_session,
664 uint32_t pcr_mask,
665 uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
666 bool use_pin,
667 ESYS_TR *ret_session,
668 TPM2B_DIGEST **ret_policy_digest,
669 TPMI_ALG_HASH *ret_pcr_bank) {
670
671 static const TPMT_SYM_DEF symmetric = {
672 .algorithm = TPM2_ALG_AES,
673 .keyBits.aes = 128,
674 .mode.aes = TPM2_ALG_CFB,
675 };
676 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
677 TPML_PCR_SELECTION pcr_selection;
678 ESYS_TR session = ESYS_TR_NONE;
679 TSS2_RC rc;
680 int r;
681
682 assert(c);
683
684 log_debug("Starting authentication session.");
685
686 if (pcr_bank != UINT16_MAX) {
687 r = tpm2_pcr_mask_good(c, pcr_bank, pcr_mask);
688 if (r < 0)
689 return r;
690 if (r == 0)
691 log_notice("Selected TPM2 PCRs are not initialized on this system, most likely due to a firmware issue. PCR policy is effectively not enforced. Proceeding anyway.");
692
693 tpm2_pcr_mask_to_selecion(pcr_mask, pcr_bank, &pcr_selection);
694 } else {
695 TPMI_ALG_HASH h;
696
697 /* No bank configured, pick automatically. Some TPM2 devices only can do SHA1. If we detect
698 * that use that, but preferably use SHA256 */
699 r = tpm2_get_best_pcr_bank(c, pcr_mask, &h);
700 if (r < 0)
701 return r;
702
703 tpm2_pcr_mask_to_selecion(pcr_mask, h, &pcr_selection);
704 }
705
706 rc = sym_Esys_StartAuthSession(
707 c,
708 primary,
709 ESYS_TR_NONE,
710 parent_session,
711 ESYS_TR_NONE,
712 ESYS_TR_NONE,
713 NULL,
714 TPM2_SE_POLICY,
715 &symmetric,
716 TPM2_ALG_SHA256,
717 &session);
718 if (rc != TSS2_RC_SUCCESS)
719 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
720 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
721
722 log_debug("Configuring PCR policy.");
723
724 rc = sym_Esys_PolicyPCR(
725 c,
726 session,
727 ESYS_TR_NONE,
728 ESYS_TR_NONE,
729 ESYS_TR_NONE,
730 NULL,
731 &pcr_selection);
732 if (rc != TSS2_RC_SUCCESS) {
733 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
734 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
735 goto finish;
736 }
737
738 if (use_pin) {
739 rc = sym_Esys_PolicyAuthValue(
740 c,
741 session,
742 ESYS_TR_NONE,
743 ESYS_TR_NONE,
744 ESYS_TR_NONE);
745 if (rc != TSS2_RC_SUCCESS) {
746 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
747 "Failed to add authValue policy to TPM: %s",
748 sym_Tss2_RC_Decode(rc));
749 goto finish;
750 }
751 }
752
753 if (DEBUG_LOGGING || ret_policy_digest) {
754 log_debug("Acquiring policy digest.");
755
756 rc = sym_Esys_PolicyGetDigest(
757 c,
758 session,
759 ESYS_TR_NONE,
760 ESYS_TR_NONE,
761 ESYS_TR_NONE,
762 &policy_digest);
763
764 if (rc != TSS2_RC_SUCCESS) {
765 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
766 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
767 goto finish;
768 }
769
770 if (DEBUG_LOGGING) {
771 _cleanup_free_ char *h = NULL;
772
773 h = hexmem(policy_digest->buffer, policy_digest->size);
774 if (!h) {
775 r = log_oom();
776 goto finish;
777 }
778
779 log_debug("Session policy digest: %s", h);
780 }
781 }
782
783 if (ret_session) {
784 *ret_session = session;
785 session = ESYS_TR_NONE;
786 }
787
788 if (ret_policy_digest)
789 *ret_policy_digest = TAKE_PTR(policy_digest);
790
791 if (ret_pcr_bank)
792 *ret_pcr_bank = pcr_selection.pcrSelections[0].hash;
793
794 r = 0;
795
796 finish:
797 session = flush_context_verbose(c, session);
798 return r;
799 }
800
801 static void hash_pin(const char *pin, size_t len, uint8_t ret_digest[static SHA256_DIGEST_SIZE]) {
802 struct sha256_ctx hash;
803
804 assert(pin);
805
806 sha256_init_ctx(&hash);
807 sha256_process_bytes(pin, len, &hash);
808 sha256_finish_ctx(&hash, ret_digest);
809
810 explicit_bzero_safe(&hash, sizeof(hash));
811 }
812
813 int tpm2_seal(
814 const char *device,
815 uint32_t pcr_mask,
816 const char *pin,
817 void **ret_secret,
818 size_t *ret_secret_size,
819 void **ret_blob,
820 size_t *ret_blob_size,
821 void **ret_pcr_hash,
822 size_t *ret_pcr_hash_size,
823 uint16_t *ret_pcr_bank,
824 uint16_t *ret_primary_alg) {
825
826 _cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
827 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
828 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
829 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
830 static const TPML_PCR_SELECTION creation_pcr = {};
831 _cleanup_(erase_and_freep) void *secret = NULL;
832 _cleanup_free_ void *blob = NULL, *hash = NULL;
833 TPM2B_SENSITIVE_CREATE hmac_sensitive;
834 ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE;
835 TPMI_ALG_PUBLIC primary_alg;
836 TPM2B_PUBLIC hmac_template;
837 TPMI_ALG_HASH pcr_bank;
838 size_t k, blob_size;
839 usec_t start;
840 TSS2_RC rc;
841 int r;
842
843 assert(ret_secret);
844 assert(ret_secret_size);
845 assert(ret_blob);
846 assert(ret_blob_size);
847 assert(ret_pcr_hash);
848 assert(ret_pcr_hash_size);
849 assert(ret_pcr_bank);
850
851 assert(pcr_mask < (UINT32_C(1) << TPM2_PCRS_MAX)); /* Support 24 PCR banks */
852
853 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
854 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
855 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
856 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
857 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
858 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
859 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
860 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
861 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
862 * LUKS2 JSON header.
863 *
864 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
865 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
866 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
867 * binding the unlocking to the TPM2 chip. */
868
869 start = now(CLOCK_MONOTONIC);
870
871 r = tpm2_init(device, &c);
872 if (r < 0)
873 return r;
874
875 r = tpm2_make_primary(c.esys_context, &primary, 0, &primary_alg);
876 if (r < 0)
877 return r;
878
879 r = tpm2_make_encryption_session(c.esys_context, primary, &session);
880 if (r < 0)
881 goto finish;
882
883 r = tpm2_make_pcr_session(c.esys_context, primary, session, pcr_mask, UINT16_MAX, !!pin, NULL,
884 &policy_digest, &pcr_bank);
885 if (r < 0)
886 goto finish;
887
888 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
889 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
890 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
891 hmac_template = (TPM2B_PUBLIC) {
892 .size = sizeof(TPMT_PUBLIC),
893 .publicArea = {
894 .type = TPM2_ALG_KEYEDHASH,
895 .nameAlg = TPM2_ALG_SHA256,
896 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
897 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
898 .unique.keyedHash.size = 32,
899 .authPolicy = *policy_digest,
900 },
901 };
902
903 hmac_sensitive = (TPM2B_SENSITIVE_CREATE) {
904 .size = sizeof(hmac_sensitive.sensitive),
905 .sensitive.data.size = 32,
906 };
907 if (pin) {
908 hash_pin(pin, strlen(pin), hmac_sensitive.sensitive.userAuth.buffer);
909 hmac_sensitive.sensitive.userAuth.size = SHA256_DIGEST_SIZE;
910 }
911 assert(sizeof(hmac_sensitive.sensitive.data.buffer) >= hmac_sensitive.sensitive.data.size);
912
913 (void) tpm2_credit_random(c.esys_context);
914
915 log_debug("Generating secret key data.");
916
917 r = crypto_random_bytes(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
918 if (r < 0) {
919 log_error_errno(r, "Failed to generate secret key: %m");
920 goto finish;
921 }
922
923 log_debug("Creating HMAC key.");
924
925 rc = sym_Esys_Create(
926 c.esys_context,
927 primary,
928 session, /* use HMAC session to enable parameter encryption */
929 ESYS_TR_NONE,
930 ESYS_TR_NONE,
931 &hmac_sensitive,
932 &hmac_template,
933 NULL,
934 &creation_pcr,
935 &private,
936 &public,
937 NULL,
938 NULL,
939 NULL);
940 if (rc != TSS2_RC_SUCCESS) {
941 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
942 "Failed to generate HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
943 goto finish;
944 }
945
946 secret = memdup(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
947 explicit_bzero_safe(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
948 if (!secret) {
949 r = log_oom();
950 goto finish;
951 }
952
953 log_debug("Marshalling private and public part of HMAC key.");
954
955 k = ALIGN8(sizeof(*private)) + ALIGN8(sizeof(*public)); /* Some roughly sensible start value */
956 for (;;) {
957 _cleanup_free_ void *buf = NULL;
958 size_t offset = 0;
959
960 buf = malloc(k);
961 if (!buf) {
962 r = log_oom();
963 goto finish;
964 }
965
966 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, buf, k, &offset);
967 if (rc == TSS2_RC_SUCCESS) {
968 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, buf, k, &offset);
969 if (rc == TSS2_RC_SUCCESS) {
970 blob = TAKE_PTR(buf);
971 blob_size = offset;
972 break;
973 }
974 }
975 if (rc != TSS2_MU_RC_INSUFFICIENT_BUFFER) {
976 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
977 "Failed to marshal private/public key: %s", sym_Tss2_RC_Decode(rc));
978 goto finish;
979 }
980
981 if (k > SIZE_MAX / 2) {
982 r = log_oom();
983 goto finish;
984 }
985
986 k *= 2;
987 }
988
989 hash = memdup(policy_digest->buffer, policy_digest->size);
990 if (!hash)
991 return log_oom();
992
993 if (DEBUG_LOGGING)
994 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
995
996 *ret_secret = TAKE_PTR(secret);
997 *ret_secret_size = hmac_sensitive.sensitive.data.size;
998 *ret_blob = TAKE_PTR(blob);
999 *ret_blob_size = blob_size;
1000 *ret_pcr_hash = TAKE_PTR(hash);
1001 *ret_pcr_hash_size = policy_digest->size;
1002 *ret_pcr_bank = pcr_bank;
1003 *ret_primary_alg = primary_alg;
1004
1005 r = 0;
1006
1007 finish:
1008 explicit_bzero_safe(&hmac_sensitive, sizeof(hmac_sensitive));
1009 primary = flush_context_verbose(c.esys_context, primary);
1010 session = flush_context_verbose(c.esys_context, session);
1011 return r;
1012 }
1013
1014 int tpm2_unseal(
1015 const char *device,
1016 uint32_t pcr_mask,
1017 uint16_t pcr_bank,
1018 uint16_t primary_alg,
1019 const void *blob,
1020 size_t blob_size,
1021 const void *known_policy_hash,
1022 size_t known_policy_hash_size,
1023 const char *pin,
1024 void **ret_secret,
1025 size_t *ret_secret_size) {
1026
1027 _cleanup_(tpm2_context_destroy) struct tpm2_context c = {};
1028 ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_session = ESYS_TR_NONE,
1029 hmac_key = ESYS_TR_NONE;
1030 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
1031 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1032 _cleanup_(erase_and_freep) char *secret = NULL;
1033 TPM2B_PRIVATE private = {};
1034 TPM2B_PUBLIC public = {};
1035 size_t offset = 0;
1036 TSS2_RC rc;
1037 usec_t start;
1038 int r;
1039
1040 assert(blob);
1041 assert(blob_size > 0);
1042 assert(known_policy_hash_size == 0 || known_policy_hash);
1043 assert(ret_secret);
1044 assert(ret_secret_size);
1045
1046 assert(pcr_mask < (UINT32_C(1) << TPM2_PCRS_MAX)); /* Support 24 PCR banks */
1047
1048 r = dlopen_tpm2();
1049 if (r < 0)
1050 return log_error_errno(r, "TPM2 support is not installed.");
1051
1052 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
1053 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy
1054 * session. Given we pass the same parameters, this will result in the same "primary" key, and same
1055 * policy hash (the latter of course, only if the PCR values didn't change in between). We unmarshal
1056 * the encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it
1057 * is decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
1058 * and use it to unlock the LUKS2 volume. */
1059
1060 start = now(CLOCK_MONOTONIC);
1061
1062 log_debug("Unmarshalling private part of HMAC key.");
1063
1064 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
1065 if (rc != TSS2_RC_SUCCESS)
1066 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1067 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
1068
1069 log_debug("Unmarshalling public part of HMAC key.");
1070
1071 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
1072 if (rc != TSS2_RC_SUCCESS)
1073 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1074 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
1075
1076 r = tpm2_init(device, &c);
1077 if (r < 0)
1078 return r;
1079
1080 r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL);
1081 if (r < 0)
1082 return r;
1083
1084 r = tpm2_make_encryption_session(c.esys_context, primary, &hmac_session);
1085 if (r < 0)
1086 goto finish;
1087
1088 r = tpm2_make_pcr_session(c.esys_context, primary, hmac_session, pcr_mask, pcr_bank, !!pin, &session,
1089 &policy_digest, NULL);
1090 if (r < 0)
1091 goto finish;
1092
1093 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
1094 * wait until the TPM2 tells us to go away. */
1095 if (known_policy_hash_size > 0 &&
1096 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
1097 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
1098 "Current policy digest does not match stored policy digest, cancelling TPM2 authentication attempt.");
1099
1100 log_debug("Loading HMAC key into TPM.");
1101
1102 rc = sym_Esys_Load(
1103 c.esys_context,
1104 primary,
1105 hmac_session, /* use HMAC session to enable parameter encryption */
1106 ESYS_TR_NONE,
1107 ESYS_TR_NONE,
1108 &private,
1109 &public,
1110 &hmac_key);
1111 if (rc != TSS2_RC_SUCCESS) {
1112 /* If we're in dictionary attack lockout mode, we should see a lockout error here, which we
1113 * need to translate for the caller. */
1114 if (rc == TPM2_RC_LOCKOUT)
1115 r = log_error_errno(
1116 SYNTHETIC_ERRNO(ENOLCK),
1117 "TPM2 device is in dictionary attack lockout mode.");
1118 else
1119 r = log_error_errno(
1120 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1121 "Failed to load HMAC key in TPM: %s",
1122 sym_Tss2_RC_Decode(rc));
1123 goto finish;
1124 }
1125
1126 if (pin) {
1127 TPM2B_AUTH auth = {
1128 .size = SHA256_DIGEST_SIZE
1129 };
1130
1131 hash_pin(pin, strlen(pin), auth.buffer);
1132
1133 rc = sym_Esys_TR_SetAuth(c.esys_context, hmac_key, &auth);
1134 explicit_bzero_safe(&auth, sizeof(auth));
1135 if (rc != TSS2_RC_SUCCESS) {
1136 r = log_error_errno(
1137 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1138 "Failed to load PIN in TPM: %s",
1139 sym_Tss2_RC_Decode(rc));
1140 goto finish;
1141 }
1142 }
1143
1144 log_debug("Unsealing HMAC key.");
1145
1146 rc = sym_Esys_Unseal(
1147 c.esys_context,
1148 hmac_key,
1149 session,
1150 hmac_session, /* use HMAC session to enable parameter encryption */
1151 ESYS_TR_NONE,
1152 &unsealed);
1153 if (rc != TSS2_RC_SUCCESS) {
1154 r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1155 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
1156 goto finish;
1157 }
1158
1159 secret = memdup(unsealed->buffer, unsealed->size);
1160 explicit_bzero_safe(unsealed->buffer, unsealed->size);
1161 if (!secret) {
1162 r = log_oom();
1163 goto finish;
1164 }
1165
1166 if (DEBUG_LOGGING)
1167 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
1168
1169 *ret_secret = TAKE_PTR(secret);
1170 *ret_secret_size = unsealed->size;
1171
1172 r = 0;
1173
1174 finish:
1175 primary = flush_context_verbose(c.esys_context, primary);
1176 session = flush_context_verbose(c.esys_context, session);
1177 hmac_key = flush_context_verbose(c.esys_context, hmac_key);
1178 return r;
1179 }
1180
1181 #endif
1182
1183 int tpm2_list_devices(void) {
1184 #if HAVE_TPM2
1185 _cleanup_(table_unrefp) Table *t = NULL;
1186 _cleanup_(closedirp) DIR *d = NULL;
1187 int r;
1188
1189 r = dlopen_tpm2();
1190 if (r < 0)
1191 return log_error_errno(r, "TPM2 support is not installed.");
1192
1193 t = table_new("path", "device", "driver");
1194 if (!t)
1195 return log_oom();
1196
1197 d = opendir("/sys/class/tpmrm");
1198 if (!d) {
1199 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
1200 if (errno != ENOENT)
1201 return -errno;
1202 } else {
1203 for (;;) {
1204 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
1205 struct dirent *de;
1206
1207 de = readdir_no_dot(d);
1208 if (!de)
1209 break;
1210
1211 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
1212 if (!device_path)
1213 return log_oom();
1214
1215 r = readlink_malloc(device_path, &device);
1216 if (r < 0)
1217 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
1218 else {
1219 driver_path = path_join(device_path, "driver");
1220 if (!driver_path)
1221 return log_oom();
1222
1223 r = readlink_malloc(driver_path, &driver);
1224 if (r < 0)
1225 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
1226 }
1227
1228 node = path_join("/dev", de->d_name);
1229 if (!node)
1230 return log_oom();
1231
1232 r = table_add_many(
1233 t,
1234 TABLE_PATH, node,
1235 TABLE_STRING, device ? last_path_component(device) : NULL,
1236 TABLE_STRING, driver ? last_path_component(driver) : NULL);
1237 if (r < 0)
1238 return table_log_add_error(r);
1239 }
1240 }
1241
1242 if (table_get_rows(t) <= 1) {
1243 log_info("No suitable TPM2 devices found.");
1244 return 0;
1245 }
1246
1247 r = table_print(t, stdout);
1248 if (r < 0)
1249 return log_error_errno(r, "Failed to show device table: %m");
1250
1251 return 0;
1252 #else
1253 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1254 "TPM2 not supported on this build.");
1255 #endif
1256 }
1257
1258 int tpm2_find_device_auto(
1259 int log_level, /* log level when no device is found */
1260 char **ret) {
1261 #if HAVE_TPM2
1262 _cleanup_(closedirp) DIR *d = NULL;
1263 int r;
1264
1265 r = dlopen_tpm2();
1266 if (r < 0)
1267 return log_error_errno(r, "TPM2 support is not installed.");
1268
1269 d = opendir("/sys/class/tpmrm");
1270 if (!d) {
1271 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
1272 "Failed to open /sys/class/tpmrm: %m");
1273 if (errno != ENOENT)
1274 return -errno;
1275 } else {
1276 _cleanup_free_ char *node = NULL;
1277
1278 for (;;) {
1279 struct dirent *de;
1280
1281 de = readdir_no_dot(d);
1282 if (!de)
1283 break;
1284
1285 if (node)
1286 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
1287 "More than one TPM2 (tpmrm) device found.");
1288
1289 node = path_join("/dev", de->d_name);
1290 if (!node)
1291 return log_oom();
1292 }
1293
1294 if (node) {
1295 *ret = TAKE_PTR(node);
1296 return 0;
1297 }
1298 }
1299
1300 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
1301 #else
1302 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1303 "TPM2 not supported on this build.");
1304 #endif
1305 }
1306
1307 int tpm2_parse_pcrs(const char *s, uint32_t *ret) {
1308 const char *p = s;
1309 uint32_t mask = 0;
1310 int r;
1311
1312 assert(s);
1313
1314 if (isempty(s)) {
1315 *ret = 0;
1316 return 0;
1317 }
1318
1319 /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
1320 * and most other tools expect comma separated PCR specifications. We also support "+" since in
1321 * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
1322 * avoid escaping. */
1323
1324 for (;;) {
1325 _cleanup_free_ char *pcr = NULL;
1326 unsigned n;
1327
1328 r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
1329 if (r == 0)
1330 break;
1331 if (r < 0)
1332 return log_error_errno(r, "Failed to parse PCR list: %s", s);
1333
1334 r = safe_atou(pcr, &n);
1335 if (r < 0)
1336 return log_error_errno(r, "Failed to parse PCR number: %s", pcr);
1337 if (n >= TPM2_PCRS_MAX)
1338 return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
1339 "PCR number out of range (valid range 0…23): %u", n);
1340
1341 mask |= UINT32_C(1) << n;
1342 }
1343
1344 *ret = mask;
1345 return 0;
1346 }
1347
1348 int tpm2_make_luks2_json(
1349 int keyslot,
1350 uint32_t pcr_mask,
1351 uint16_t pcr_bank,
1352 uint16_t primary_alg,
1353 const void *blob,
1354 size_t blob_size,
1355 const void *policy_hash,
1356 size_t policy_hash_size,
1357 TPM2Flags flags,
1358 JsonVariant **ret) {
1359
1360 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *a = NULL;
1361 _cleanup_free_ char *keyslot_as_string = NULL;
1362 JsonVariant* pcr_array[TPM2_PCRS_MAX];
1363 unsigned n_pcrs = 0;
1364 int r;
1365
1366 assert(blob || blob_size == 0);
1367 assert(policy_hash || policy_hash_size == 0);
1368
1369 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
1370 return -ENOMEM;
1371
1372 for (unsigned i = 0; i < ELEMENTSOF(pcr_array); i++) {
1373 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
1374 continue;
1375
1376 r = json_variant_new_integer(pcr_array + n_pcrs, i);
1377 if (r < 0) {
1378 json_variant_unref_many(pcr_array, n_pcrs);
1379 return -ENOMEM;
1380 }
1381
1382 n_pcrs++;
1383 }
1384
1385 r = json_variant_new_array(&a, pcr_array, n_pcrs);
1386 json_variant_unref_many(pcr_array, n_pcrs);
1387 if (r < 0)
1388 return -ENOMEM;
1389
1390 r = json_build(&v,
1391 JSON_BUILD_OBJECT(
1392 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
1393 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
1394 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
1395 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(a)),
1396 JSON_BUILD_PAIR_CONDITION(!!tpm2_pcr_bank_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_pcr_bank_to_string(pcr_bank))),
1397 JSON_BUILD_PAIR_CONDITION(!!tpm2_primary_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_primary_alg_to_string(primary_alg))),
1398 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
1399 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)))
1400 );
1401 if (r < 0)
1402 return r;
1403
1404 if (ret)
1405 *ret = TAKE_PTR(v);
1406
1407 return keyslot;
1408 }
1409
1410 const char *tpm2_pcr_bank_to_string(uint16_t bank) {
1411 /* For now, let's officially only support these two. We can extend this later on, should the need
1412 * arise. */
1413 if (bank == TPM2_ALG_SHA256)
1414 return "sha256";
1415 if (bank == TPM2_ALG_SHA1)
1416 return "sha1";
1417 return NULL;
1418 }
1419
1420 int tpm2_pcr_bank_from_string(const char *bank) {
1421 if (streq_ptr(bank, "sha256"))
1422 return TPM2_ALG_SHA256;
1423 if (streq_ptr(bank, "sha1"))
1424 return TPM2_ALG_SHA1;
1425 return -EINVAL;
1426 }
1427
1428 const char *tpm2_primary_alg_to_string(uint16_t alg) {
1429 if (alg == TPM2_ALG_ECC)
1430 return "ecc";
1431 if (alg == TPM2_ALG_RSA)
1432 return "rsa";
1433 return NULL;
1434 }
1435
1436 int tpm2_primary_alg_from_string(const char *alg) {
1437 if (streq_ptr(alg, "ecc"))
1438 return TPM2_ALG_ECC;
1439 if (streq_ptr(alg, "rsa"))
1440 return TPM2_ALG_RSA;
1441 return -EINVAL;
1442 }
1443
1444 Tpm2Support tpm2_support(void) {
1445 Tpm2Support support = TPM2_SUPPORT_NONE;
1446 int r;
1447
1448 if (detect_container() <= 0) {
1449 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
1450 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
1451 * let's assume containers never have a TPM, at least for now. */
1452
1453 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
1454 if (r < 0) {
1455 if (r != -ENOENT)
1456 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
1457 } else if (r == 0) /* populated! */
1458 support |= TPM2_SUPPORT_DRIVER;
1459 }
1460
1461 if (efi_has_tpm2())
1462 support |= TPM2_SUPPORT_FIRMWARE;
1463
1464 #if HAVE_TPM2
1465 support |= TPM2_SUPPORT_SYSTEM;
1466 #endif
1467
1468 return support;
1469 }