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