]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/tpm2-util.c
use FOREACH_ELEMENT
[thirdparty/systemd.git] / src / shared / tpm2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <sys/file.h>
4
5 #include "alloc-util.h"
6 #include "constants.h"
7 #include "creds-util.h"
8 #include "cryptsetup-util.h"
9 #include "dirent-util.h"
10 #include "dlfcn-util.h"
11 #include "efi-api.h"
12 #include "extract-word.h"
13 #include "fd-util.h"
14 #include "fileio.h"
15 #include "format-table.h"
16 #include "fs-util.h"
17 #include "hexdecoct.h"
18 #include "hmac.h"
19 #include "initrd-util.h"
20 #include "io-util.h"
21 #include "lock-util.h"
22 #include "log.h"
23 #include "logarithm.h"
24 #include "memory-util.h"
25 #include "mkdir.h"
26 #include "nulstr-util.h"
27 #include "parse-util.h"
28 #include "random-util.h"
29 #include "recurse-dir.h"
30 #include "sha256.h"
31 #include "sort-util.h"
32 #include "stat-util.h"
33 #include "string-table.h"
34 #include "sync-util.h"
35 #include "time-util.h"
36 #include "tpm2-util.h"
37 #include "virt.h"
38
39 #if HAVE_TPM2
40 static void *libtss2_esys_dl = NULL;
41 static void *libtss2_rc_dl = NULL;
42 static void *libtss2_mu_dl = NULL;
43
44 static DLSYM_FUNCTION(Esys_Create);
45 static DLSYM_FUNCTION(Esys_CreateLoaded);
46 static DLSYM_FUNCTION(Esys_CreatePrimary);
47 static DLSYM_FUNCTION(Esys_EvictControl);
48 static DLSYM_FUNCTION(Esys_Finalize);
49 static DLSYM_FUNCTION(Esys_FlushContext);
50 static DLSYM_FUNCTION(Esys_Free);
51 static DLSYM_FUNCTION(Esys_GetCapability);
52 static DLSYM_FUNCTION(Esys_GetRandom);
53 static DLSYM_FUNCTION(Esys_Import);
54 static DLSYM_FUNCTION(Esys_Initialize);
55 static DLSYM_FUNCTION(Esys_Load);
56 static DLSYM_FUNCTION(Esys_LoadExternal);
57 static DLSYM_FUNCTION(Esys_NV_DefineSpace);
58 static DLSYM_FUNCTION(Esys_NV_UndefineSpace);
59 static DLSYM_FUNCTION(Esys_NV_Write);
60 static DLSYM_FUNCTION(Esys_PCR_Extend);
61 static DLSYM_FUNCTION(Esys_PCR_Read);
62 static DLSYM_FUNCTION(Esys_PolicyAuthValue);
63 static DLSYM_FUNCTION(Esys_PolicyAuthorize);
64 static DLSYM_FUNCTION(Esys_PolicyAuthorizeNV);
65 static DLSYM_FUNCTION(Esys_PolicyGetDigest);
66 static DLSYM_FUNCTION(Esys_PolicyOR);
67 static DLSYM_FUNCTION(Esys_PolicyPCR);
68 static DLSYM_FUNCTION(Esys_ReadPublic);
69 static DLSYM_FUNCTION(Esys_StartAuthSession);
70 static DLSYM_FUNCTION(Esys_Startup);
71 static DLSYM_FUNCTION(Esys_TestParms);
72 static DLSYM_FUNCTION(Esys_TR_Close);
73 static DLSYM_FUNCTION(Esys_TR_Deserialize);
74 static DLSYM_FUNCTION(Esys_TR_FromTPMPublic);
75 static DLSYM_FUNCTION(Esys_TR_GetName);
76 static DLSYM_FUNCTION(Esys_TR_GetTpmHandle);
77 static DLSYM_FUNCTION(Esys_TR_Serialize);
78 static DLSYM_FUNCTION(Esys_TR_SetAuth);
79 static DLSYM_FUNCTION(Esys_TRSess_GetAttributes);
80 static DLSYM_FUNCTION(Esys_TRSess_SetAttributes);
81 static DLSYM_FUNCTION(Esys_Unseal);
82 static DLSYM_FUNCTION(Esys_VerifySignature);
83
84 static DLSYM_FUNCTION(Tss2_MU_TPM2_CC_Marshal);
85 static DLSYM_FUNCTION(Tss2_MU_TPM2_HANDLE_Marshal);
86 static DLSYM_FUNCTION(Tss2_MU_TPM2B_DIGEST_Marshal);
87 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal);
88 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal);
89 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NAME_Marshal);
90 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Marshal);
91 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Unmarshal);
92 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Marshal);
93 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Unmarshal);
94 static DLSYM_FUNCTION(Tss2_MU_TPM2B_SENSITIVE_Marshal);
95 static DLSYM_FUNCTION(Tss2_MU_TPML_PCR_SELECTION_Marshal);
96 static DLSYM_FUNCTION(Tss2_MU_TPMS_NV_PUBLIC_Marshal);
97 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Marshal);
98 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal);
99 static DLSYM_FUNCTION(Tss2_MU_TPMS_ECC_POINT_Marshal);
100 static DLSYM_FUNCTION(Tss2_MU_TPMT_HA_Marshal);
101 static DLSYM_FUNCTION(Tss2_MU_TPMT_PUBLIC_Marshal);
102 static DLSYM_FUNCTION(Tss2_MU_UINT32_Marshal);
103
104 static DLSYM_FUNCTION(Tss2_RC_Decode);
105
106 int dlopen_tpm2(void) {
107 int r;
108
109 r = dlopen_many_sym_or_warn(
110 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
111 DLSYM_ARG(Esys_Create),
112 DLSYM_ARG(Esys_CreateLoaded),
113 DLSYM_ARG(Esys_CreatePrimary),
114 DLSYM_ARG(Esys_EvictControl),
115 DLSYM_ARG(Esys_Finalize),
116 DLSYM_ARG(Esys_FlushContext),
117 DLSYM_ARG(Esys_Free),
118 DLSYM_ARG(Esys_GetCapability),
119 DLSYM_ARG(Esys_GetRandom),
120 DLSYM_ARG(Esys_Import),
121 DLSYM_ARG(Esys_Initialize),
122 DLSYM_ARG(Esys_Load),
123 DLSYM_ARG(Esys_LoadExternal),
124 DLSYM_ARG(Esys_NV_DefineSpace),
125 DLSYM_ARG(Esys_NV_UndefineSpace),
126 DLSYM_ARG(Esys_NV_Write),
127 DLSYM_ARG(Esys_PCR_Extend),
128 DLSYM_ARG(Esys_PCR_Read),
129 DLSYM_ARG(Esys_PolicyAuthValue),
130 DLSYM_ARG(Esys_PolicyAuthorize),
131 DLSYM_ARG(Esys_PolicyAuthorizeNV),
132 DLSYM_ARG(Esys_PolicyGetDigest),
133 DLSYM_ARG(Esys_PolicyOR),
134 DLSYM_ARG(Esys_PolicyPCR),
135 DLSYM_ARG(Esys_ReadPublic),
136 DLSYM_ARG(Esys_StartAuthSession),
137 DLSYM_ARG(Esys_Startup),
138 DLSYM_ARG(Esys_TestParms),
139 DLSYM_ARG(Esys_TR_Close),
140 DLSYM_ARG(Esys_TR_Deserialize),
141 DLSYM_ARG(Esys_TR_FromTPMPublic),
142 DLSYM_ARG(Esys_TR_GetName),
143 DLSYM_ARG(Esys_TR_Serialize),
144 DLSYM_ARG(Esys_TR_SetAuth),
145 DLSYM_ARG(Esys_TRSess_GetAttributes),
146 DLSYM_ARG(Esys_TRSess_SetAttributes),
147 DLSYM_ARG(Esys_Unseal),
148 DLSYM_ARG(Esys_VerifySignature));
149 if (r < 0)
150 return r;
151
152 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
153 * version of 2.4.0 this sym can be moved up to the normal list above. */
154 r = dlsym_many_or_warn(libtss2_esys_dl, LOG_DEBUG, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle));
155 if (r < 0)
156 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
157
158 r = dlopen_many_sym_or_warn(
159 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
160 DLSYM_ARG(Tss2_RC_Decode));
161 if (r < 0)
162 return r;
163
164 return dlopen_many_sym_or_warn(
165 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
166 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
167 DLSYM_ARG(Tss2_MU_TPM2_HANDLE_Marshal),
168 DLSYM_ARG(Tss2_MU_TPM2B_DIGEST_Marshal),
169 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal),
170 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal),
171 DLSYM_ARG(Tss2_MU_TPM2B_NAME_Marshal),
172 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
173 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
174 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
175 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
176 DLSYM_ARG(Tss2_MU_TPM2B_SENSITIVE_Marshal),
177 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal),
178 DLSYM_ARG(Tss2_MU_TPMS_NV_PUBLIC_Marshal),
179 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Marshal),
180 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal),
181 DLSYM_ARG(Tss2_MU_TPMS_ECC_POINT_Marshal),
182 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal),
183 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal),
184 DLSYM_ARG(Tss2_MU_UINT32_Marshal));
185 }
186
187 void Esys_Freep(void *p) {
188 if (*(void**) p)
189 sym_Esys_Free(*(void**) p);
190 }
191
192 /* Get a specific TPM capability (or capabilities).
193 *
194 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
195 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
196 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
197 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
198 *
199 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
200 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
201 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
202 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
203 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
204 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
205 * capability category may have more specific requirements than described here; see the spec for exact
206 * details. */
207 static int tpm2_get_capability(
208 Tpm2Context *c,
209 TPM2_CAP capability,
210 uint32_t property,
211 uint32_t count,
212 TPMU_CAPABILITIES *ret_capability_data) {
213
214 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *capabilities = NULL;
215 TPMI_YES_NO more;
216 TSS2_RC rc;
217
218 assert(c);
219
220 log_debug("Getting TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " count %" PRIu32 ".",
221 capability, property, count);
222
223 rc = sym_Esys_GetCapability(
224 c->esys_context,
225 ESYS_TR_NONE,
226 ESYS_TR_NONE,
227 ESYS_TR_NONE,
228 capability,
229 property,
230 count,
231 &more,
232 &capabilities);
233 if (rc == TPM2_RC_VALUE)
234 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
235 "Requested TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " apparently doesn't exist: %s",
236 capability, property, sym_Tss2_RC_Decode(rc));
237 if (rc != TSS2_RC_SUCCESS)
238 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
239 "Failed to get TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 ": %s",
240 capability, property, sym_Tss2_RC_Decode(rc));
241 if (capabilities->capability != capability)
242 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
243 "TPM provided wrong capability: 0x%04" PRIx32 " instead of 0x%04" PRIx32 ".",
244 capabilities->capability, capability);
245
246 if (ret_capability_data)
247 *ret_capability_data = capabilities->data;
248
249 return more == TPM2_YES;
250 }
251
252 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
253
254 static int tpm2_cache_capabilities(Tpm2Context *c) {
255 TPMU_CAPABILITIES capability;
256 int r;
257
258 assert(c);
259
260 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
261 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
262 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
263 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
264 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
265 * changed while we are performing some operation, it's reasonable to assume it will break us even if
266 * we don't cache the algorithms, thus they should be "safe" to cache. */
267 TPM2_ALG_ID current_alg = TPM2_ALG_FIRST;
268 for (;;) {
269 r = tpm2_get_capability(
270 c,
271 TPM2_CAP_ALGS,
272 (uint32_t) current_alg, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
273 TPM2_MAX_CAP_ALGS,
274 &capability);
275 if (r < 0)
276 return r;
277
278 TPML_ALG_PROPERTY algorithms = capability.algorithms;
279
280 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
281 * there are no more. */
282 assert(algorithms.count > 0);
283
284 if (!GREEDY_REALLOC_APPEND(
285 c->capability_algorithms,
286 c->n_capability_algorithms,
287 algorithms.algProperties,
288 algorithms.count))
289 return log_oom_debug();
290
291 if (r == 0)
292 break;
293
294 /* Set current_alg to alg id after last alg id the TPM provided */
295 current_alg = algorithms.algProperties[algorithms.count - 1].alg + 1;
296 }
297
298 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
299 * while running, but that would be crazy, so let's hope it is not possible. */
300 TPM2_CC current_cc = TPM2_CC_FIRST;
301 for (;;) {
302 r = tpm2_get_capability(
303 c,
304 TPM2_CAP_COMMANDS,
305 current_cc,
306 TPM2_MAX_CAP_CC,
307 &capability);
308 if (r < 0)
309 return r;
310
311 TPML_CCA commands = capability.command;
312
313 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
314 * there are no more. */
315 assert(commands.count > 0);
316
317 if (!GREEDY_REALLOC_APPEND(
318 c->capability_commands,
319 c->n_capability_commands,
320 commands.commandAttributes,
321 commands.count))
322 return log_oom_debug();
323
324 if (r == 0)
325 break;
326
327 /* Set current_cc to index after last cc the TPM provided */
328 current_cc = TPMA_CC_TO_TPM2_CC(commands.commandAttributes[commands.count - 1]) + 1;
329 }
330
331 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
332 * while running, but that would be crazy, so let's hope it is not possible. */
333 TPM2_ECC_CURVE current_ecc_curve = TPM2_ECC_NONE;
334 for (;;) {
335 r = tpm2_get_capability(
336 c,
337 TPM2_CAP_ECC_CURVES,
338 current_ecc_curve,
339 TPM2_MAX_ECC_CURVES,
340 &capability);
341 if (r == -ENXIO) /* If the TPM doesn't support ECC, it might return TPM2_RC_VALUE rather than capability.eccCurves == 0 */
342 break;
343 if (r < 0)
344 return r;
345
346 TPML_ECC_CURVE ecc_curves = capability.eccCurves;
347
348 /* ECC support isn't required */
349 if (ecc_curves.count == 0)
350 break;
351
352 if (!GREEDY_REALLOC_APPEND(
353 c->capability_ecc_curves,
354 c->n_capability_ecc_curves,
355 ecc_curves.eccCurves,
356 ecc_curves.count))
357 return log_oom_debug();
358
359 if (r == 0)
360 break;
361
362 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
363 current_ecc_curve = ecc_curves.eccCurves[ecc_curves.count - 1] + 1;
364 }
365
366 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
367 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
368 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
369 * safely assume the TPM PCR allocation will not change while we are using it. */
370 r = tpm2_get_capability(
371 c,
372 TPM2_CAP_PCRS,
373 /* property= */ 0,
374 /* count= */ 1,
375 &capability);
376 if (r < 0)
377 return r;
378 if (r == 1)
379 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
380 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
381 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
382 * this command with the full PCR allocation and moreData will be NO." */
383 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
384 c->capability_pcrs = capability.assignedPCR;
385
386 return 0;
387 }
388
389 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
390 * TPMA_ALGORITHM is provided, otherwise false. */
391 static bool tpm2_get_capability_alg(Tpm2Context *c, TPM2_ALG_ID alg, TPMA_ALGORITHM *ret) {
392 assert(c);
393
394 FOREACH_ARRAY(alg_prop, c->capability_algorithms, c->n_capability_algorithms)
395 if (alg_prop->alg == alg) {
396 if (ret)
397 *ret = alg_prop->algProperties;
398 return true;
399 }
400
401 log_debug("TPM does not support alg 0x%02" PRIx16 ".", alg);
402 if (ret)
403 *ret = 0;
404
405 return false;
406 }
407
408 bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg) {
409 return tpm2_get_capability_alg(c, alg, NULL);
410 }
411
412 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
413 * otherwise false. */
414 static bool tpm2_get_capability_command(Tpm2Context *c, TPM2_CC command, TPMA_CC *ret) {
415 assert(c);
416
417 FOREACH_ARRAY(cca, c->capability_commands, c->n_capability_commands)
418 if (TPMA_CC_TO_TPM2_CC(*cca) == command) {
419 if (ret)
420 *ret = *cca;
421 return true;
422 }
423
424 log_debug("TPM does not support command 0x%04" PRIx32 ".", command);
425 if (ret)
426 *ret = 0;
427
428 return false;
429 }
430
431 bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command) {
432 return tpm2_get_capability_command(c, command, NULL);
433 }
434
435 /* Returns true if the TPM supports the ECC curve, otherwise false. */
436 bool tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE ecc_curve) {
437 assert(c);
438
439 FOREACH_ARRAY(curve, c->capability_ecc_curves, c->n_capability_ecc_curves)
440 if (*curve == ecc_curve)
441 return true;
442
443 log_debug("TPM does not support ECC curve 0x%" PRIx16 ".", ecc_curve);
444 return false;
445 }
446
447 /* Query the TPM for populated handles.
448 *
449 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
450 * contain only populated handle addresses (which might not include the requested handle). The number of
451 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
452 * range (i.e. handle & 0xff000000).
453 *
454 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
455 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
456 static int tpm2_get_capability_handles(
457 Tpm2Context *c,
458 TPM2_HANDLE start,
459 size_t max,
460 TPM2_HANDLE **ret_handles,
461 size_t *ret_n_handles) {
462
463 _cleanup_free_ TPM2_HANDLE *handles = NULL;
464 size_t n_handles = 0;
465 TPM2_HANDLE current = start;
466 int r = 0;
467
468 assert(c);
469 assert(ret_handles);
470 assert(ret_n_handles);
471
472 max = MIN(max, UINT32_MAX);
473
474 while (max > 0) {
475 TPMU_CAPABILITIES capability;
476 r = tpm2_get_capability(c, TPM2_CAP_HANDLES, current, (uint32_t) max, &capability);
477 if (r < 0)
478 return r;
479
480 TPML_HANDLE handle_list = capability.handles;
481 if (handle_list.count == 0)
482 break;
483
484 assert(handle_list.count <= max);
485
486 if (n_handles > SIZE_MAX - handle_list.count)
487 return log_oom_debug();
488
489 if (!GREEDY_REALLOC_APPEND(handles, n_handles, handle_list.handle, handle_list.count))
490 return log_oom_debug();
491
492 max -= handle_list.count;
493
494 /* Update current to the handle index after the last handle in the list. */
495 current = handles[n_handles - 1] + 1;
496
497 if (r == 0)
498 /* No more handles in this range. */
499 break;
500 }
501
502 *ret_handles = TAKE_PTR(handles);
503 *ret_n_handles = n_handles;
504
505 return r;
506 }
507
508 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
509 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
510
511 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
512 static int tpm2_get_capability_handle(Tpm2Context *c, TPM2_HANDLE handle) {
513 _cleanup_free_ TPM2_HANDLE *handles = NULL;
514 size_t n_handles = 0;
515 int r;
516
517 r = tpm2_get_capability_handles(c, handle, 1, &handles, &n_handles);
518 if (r < 0)
519 return r;
520
521 return n_handles == 0 ? false : handles[0] == handle;
522 }
523
524 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
525 bool tpm2_test_parms(Tpm2Context *c, TPMI_ALG_PUBLIC alg, const TPMU_PUBLIC_PARMS *parms) {
526 TSS2_RC rc;
527
528 assert(c);
529 assert(parms);
530
531 TPMT_PUBLIC_PARMS parameters = {
532 .type = alg,
533 .parameters = *parms,
534 };
535
536 rc = sym_Esys_TestParms(c->esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parameters);
537 if (rc != TSS2_RC_SUCCESS)
538 /* The spec says if the parms are not supported the TPM returns "...the appropriate
539 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
540 * unmarshaling errors, instead of checking for them all here, let's just assume any error
541 * indicates unsupported parms, and log the specific error text. */
542 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc));
543
544 return rc == TSS2_RC_SUCCESS;
545 }
546
547 static bool tpm2_supports_tpmt_public(Tpm2Context *c, const TPMT_PUBLIC *public) {
548 assert(c);
549 assert(public);
550
551 return tpm2_test_parms(c, public->type, &public->parameters);
552 }
553
554 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context *c, const TPMT_SYM_DEF_OBJECT *parameters) {
555 assert(c);
556 assert(parameters);
557
558 TPMU_PUBLIC_PARMS parms = {
559 .symDetail.sym = *parameters,
560 };
561
562 return tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms);
563 }
564
565 static bool tpm2_supports_tpmt_sym_def(Tpm2Context *c, const TPMT_SYM_DEF *parameters) {
566 assert(c);
567 assert(parameters);
568
569 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
570 * functionally identical. */
571 TPMT_SYM_DEF_OBJECT object = {
572 .algorithm = parameters->algorithm,
573 .keyBits = parameters->keyBits,
574 .mode = parameters->mode,
575 };
576
577 return tpm2_supports_tpmt_sym_def_object(c, &object);
578 }
579
580 static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
581 if (!c)
582 return NULL;
583
584 if (c->esys_context)
585 sym_Esys_Finalize(&c->esys_context);
586
587 c->tcti_context = mfree(c->tcti_context);
588 c->tcti_dl = safe_dlclose(c->tcti_dl);
589
590 c->capability_algorithms = mfree(c->capability_algorithms);
591 c->capability_commands = mfree(c->capability_commands);
592 c->capability_ecc_curves = mfree(c->capability_ecc_curves);
593
594 return mfree(c);
595 }
596
597 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
598
599 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB = {
600 .algorithm = TPM2_ALG_AES,
601 .keyBits.aes = 128,
602 .mode.aes = TPM2_ALG_CFB, /* The spec requires sessions to use CFB. */
603 };
604
605 int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
606 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = NULL;
607 TSS2_RC rc;
608 int r;
609
610 assert(ret_context);
611
612 context = new(Tpm2Context, 1);
613 if (!context)
614 return log_oom_debug();
615
616 *context = (Tpm2Context) {
617 .n_ref = 1,
618 };
619
620 r = dlopen_tpm2();
621 if (r < 0)
622 return log_debug_errno(r, "TPM2 support not installed: %m");
623
624 if (!device) {
625 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
626 if (device)
627 /* Setting the env var to an empty string forces tpm2-tss' own device picking
628 * logic to be used. */
629 device = empty_to_null(device);
630 else
631 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
632 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
633 * might be used and we really don't want that, since it is a system service and that creates
634 * various ordering issues/deadlocks during early boot. */
635 device = "device:/dev/tpmrm0";
636 }
637
638 if (device) {
639 const char *param, *driver, *fn;
640 const TSS2_TCTI_INFO* info;
641 TSS2_TCTI_INFO_FUNC func;
642 size_t sz = 0;
643
644 param = strchr(device, ':');
645 if (param) {
646 /* Syntax #1: Pair of driver string and arbitrary parameter */
647 driver = strndupa_safe(device, param - device);
648 if (isempty(driver))
649 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
650
651 param++;
652 } else if (path_is_absolute(device) && path_is_valid(device)) {
653 /* Syntax #2: TPM device node */
654 driver = "device";
655 param = device;
656 } else
657 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
658
659 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
660
661 fn = strjoina("libtss2-tcti-", driver, ".so.0");
662
663 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
664 if (!filename_is_valid(fn))
665 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
666
667 context->tcti_dl = dlopen(fn, RTLD_NOW);
668 if (!context->tcti_dl)
669 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
670
671 log_debug("Loaded '%s' via dlopen()", fn);
672
673 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
674 if (!func)
675 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
676 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
677 dlerror());
678
679 info = func();
680 if (!info)
681 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
682
683 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
684
685 rc = info->init(NULL, &sz, NULL);
686 if (rc != TPM2_RC_SUCCESS)
687 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
688 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
689
690 context->tcti_context = malloc0(sz);
691 if (!context->tcti_context)
692 return log_oom_debug();
693
694 rc = info->init(context->tcti_context, &sz, param);
695 if (rc != TPM2_RC_SUCCESS)
696 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
697 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
698 }
699
700 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
701 if (rc != TSS2_RC_SUCCESS)
702 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
703 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
704
705 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
706 if (rc == TPM2_RC_INITIALIZE)
707 log_debug("TPM already started up.");
708 else if (rc == TSS2_RC_SUCCESS)
709 log_debug("TPM successfully started up.");
710 else
711 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
712 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
713
714 r = tpm2_cache_capabilities(context);
715 if (r < 0)
716 return log_debug_errno(r, "Failed to cache TPM capabilities: %m");
717
718 /* We require AES and CFB support for session encryption. */
719 if (!tpm2_supports_alg(context, TPM2_ALG_AES))
720 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES.");
721
722 if (!tpm2_supports_alg(context, TPM2_ALG_CFB))
723 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support CFB.");
724
725 if (!tpm2_supports_tpmt_sym_def(context, &SESSION_TEMPLATE_SYM_AES_128_CFB))
726 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES-128-CFB.");
727
728 *ret_context = TAKE_PTR(context);
729
730 return 0;
731 }
732
733 static void tpm2_handle_cleanup(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, bool flush) {
734 TSS2_RC rc;
735
736 if (!esys_context || esys_handle == ESYS_TR_NONE)
737 return;
738
739 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
740 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
741 * as removing its corresponding handle from the actual TPM. */
742 if (flush)
743 rc = sym_Esys_FlushContext(esys_context, esys_handle);
744 else
745 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
746 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
747 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
748 * directly affects us; for example the src/test/test-tpm2.c test function
749 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
750 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
751 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
752 * references will be cleaned up when we free our ESYS_CONTEXT.
753 *
754 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
755 rc = TSS2_RC_SUCCESS; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
756 if (rc != TSS2_RC_SUCCESS)
757 /* We ignore failures here (besides debug logging), since this is called in error paths,
758 * where we cannot do anything about failures anymore. And when it is called in successful
759 * codepaths by this time we already did what we wanted to do, and got the results we wanted
760 * so there's no reason to make this fail more loudly than necessary. */
761 log_debug("Failed to %s TPM handle, ignoring: %s", flush ? "flush" : "close", sym_Tss2_RC_Decode(rc));
762 }
763
764 Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
765 if (!handle)
766 return NULL;
767
768 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
769 if (context)
770 tpm2_handle_cleanup(context->esys_context, handle->esys_handle, handle->flush);
771
772 return mfree(handle);
773 }
774
775 int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
776 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
777
778 assert(ret_handle);
779
780 handle = new(Tpm2Handle, 1);
781 if (!handle)
782 return log_oom_debug();
783
784 *handle = (Tpm2Handle) {
785 .tpm2_context = tpm2_context_ref(context),
786 .esys_handle = ESYS_TR_NONE,
787 .flush = true,
788 };
789
790 *ret_handle = TAKE_PTR(handle);
791
792 return 0;
793 }
794
795 static int tpm2_read_public(
796 Tpm2Context *c,
797 const Tpm2Handle *session,
798 const Tpm2Handle *handle,
799 TPM2B_PUBLIC **ret_public,
800 TPM2B_NAME **ret_name,
801 TPM2B_NAME **ret_qname) {
802
803 TSS2_RC rc;
804
805 assert(c);
806 assert(handle);
807
808 rc = sym_Esys_ReadPublic(
809 c->esys_context,
810 handle->esys_handle,
811 session ? session->esys_handle : ESYS_TR_NONE,
812 ESYS_TR_NONE,
813 ESYS_TR_NONE,
814 ret_public,
815 ret_name,
816 ret_qname);
817 if (rc != TSS2_RC_SUCCESS)
818 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
819 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
820
821 return 0;
822 }
823
824 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
825 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
826 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
827 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
828 * Tpm2Handle. */
829 int tpm2_index_to_handle(
830 Tpm2Context *c,
831 TPM2_HANDLE index,
832 const Tpm2Handle *session,
833 TPM2B_PUBLIC **ret_public,
834 TPM2B_NAME **ret_name,
835 TPM2B_NAME **ret_qname,
836 Tpm2Handle **ret_handle) {
837
838 TSS2_RC rc;
839 int r;
840
841 assert(c);
842
843 /* Only allow persistent, transient, or NV index handle types. */
844 switch (TPM2_HANDLE_TYPE(index)) {
845 case TPM2_HT_PERSISTENT:
846 case TPM2_HT_NV_INDEX:
847 case TPM2_HT_TRANSIENT:
848 break;
849 case TPM2_HT_PCR:
850 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
851 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
852 "Invalid handle 0x%08" PRIx32 " (in PCR range).", index);
853 case TPM2_HT_HMAC_SESSION:
854 case TPM2_HT_POLICY_SESSION:
855 /* Session indexes are only used internally by tpm2-tss (or lower code) */
856 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
857 "Invalid handle 0x%08" PRIx32 " (in session range).", index);
858 case TPM2_HT_PERMANENT:
859 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
860 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
861 "Invalid handle 0x%08" PRIx32 " (in permanent range).", index);
862 default:
863 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
864 "Invalid handle 0x%08" PRIx32 " (in unknown range).", index);
865 }
866
867 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
868 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
869 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
870 if (TPM2_HANDLE_TYPE(index) != TPM2_HT_TRANSIENT) { // FIXME: once kernel bug is fixed, check transient handles too
871 r = tpm2_get_capability_handle(c, index);
872 if (r < 0)
873 return r;
874 if (r == 0) {
875 log_debug("TPM handle 0x%08" PRIx32 " not populated.", index);
876 if (ret_public)
877 *ret_public = NULL;
878 if (ret_name)
879 *ret_name = NULL;
880 if (ret_qname)
881 *ret_qname = NULL;
882 if (ret_handle)
883 *ret_handle = NULL;
884 return 0;
885 }
886 }
887
888 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
889 r = tpm2_handle_new(c, &handle);
890 if (r < 0)
891 return r;
892
893 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
894 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
895 handle->flush = false;
896
897 rc = sym_Esys_TR_FromTPMPublic(
898 c->esys_context,
899 index,
900 session ? session->esys_handle : ESYS_TR_NONE,
901 ESYS_TR_NONE,
902 ESYS_TR_NONE,
903 &handle->esys_handle);
904 if (rc != TSS2_RC_SUCCESS)
905 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
906 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
907
908 if (ret_public || ret_name || ret_qname) {
909 r = tpm2_read_public(c, session, handle, ret_public, ret_name, ret_qname);
910 if (r < 0)
911 return r;
912 }
913
914 if (ret_handle)
915 *ret_handle = TAKE_PTR(handle);
916
917 return 1;
918 }
919
920 /* Get the handle index for the provided Tpm2Handle. */
921 int tpm2_index_from_handle(Tpm2Context *c, const Tpm2Handle *handle, TPM2_HANDLE *ret_index) {
922 TSS2_RC rc;
923
924 assert(c);
925 assert(handle);
926 assert(ret_index);
927
928 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
929 * version of 2.4.0 this check can be removed. */
930 if (!sym_Esys_TR_GetTpmHandle)
931 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
932 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
933
934 rc = sym_Esys_TR_GetTpmHandle(c->esys_context, handle->esys_handle, ret_index);
935 if (rc != TSS2_RC_SUCCESS)
936 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
937 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc));
938
939 return 0;
940 }
941
942 /* Copy an object in the TPM at a transient handle to a persistent handle.
943 *
944 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
945 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
946 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
947 * be used.
948 *
949 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
950 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
951 * at the requested persistent handle index (or the first available if none was requested).
952 *
953 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
954 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
955 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
956 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
957 * memory for persistent storage. The persistent handle is only provided when returning 1. */
958 static int tpm2_persist_handle(
959 Tpm2Context *c,
960 const Tpm2Handle *transient_handle,
961 const Tpm2Handle *session,
962 TPMI_DH_PERSISTENT persistent_handle_index,
963 Tpm2Handle **ret_persistent_handle) {
964
965 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
966 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
967 TPMI_DH_PERSISTENT first = UINT32_C(0x81000000), last = UINT32_C(0x81ffffff);
968 TSS2_RC rc;
969 int r;
970
971 assert(c);
972 assert(transient_handle);
973
974 /* If persistent handle index specified, only try that. */
975 if (persistent_handle_index != 0) {
976 if (TPM2_HANDLE_TYPE(persistent_handle_index) != TPM2_HT_PERSISTENT)
977 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
978 "Handle not in persistent range: 0x%x", persistent_handle_index);
979
980 first = last = persistent_handle_index;
981 }
982
983 for (TPMI_DH_PERSISTENT requested = first; requested <= last; requested++) {
984 _cleanup_(tpm2_handle_freep) Tpm2Handle *persistent_handle = NULL;
985 r = tpm2_handle_new(c, &persistent_handle);
986 if (r < 0)
987 return r;
988
989 /* Since this is a persistent handle, don't flush it. */
990 persistent_handle->flush = false;
991
992 rc = sym_Esys_EvictControl(
993 c->esys_context,
994 ESYS_TR_RH_OWNER,
995 transient_handle->esys_handle,
996 session ? session->esys_handle : ESYS_TR_PASSWORD,
997 ESYS_TR_NONE,
998 ESYS_TR_NONE,
999 requested,
1000 &persistent_handle->esys_handle);
1001 if (rc == TSS2_RC_SUCCESS) {
1002 if (ret_persistent_handle)
1003 *ret_persistent_handle = TAKE_PTR(persistent_handle);
1004
1005 return 1;
1006 }
1007 if (rc != TPM2_RC_NV_DEFINED)
1008 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1009 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc));
1010 }
1011
1012 if (ret_persistent_handle)
1013 *ret_persistent_handle = NULL;
1014
1015 return 0;
1016 }
1017
1018 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
1019
1020 static int tpm2_credit_random(Tpm2Context *c) {
1021 size_t rps, done = 0;
1022 TSS2_RC rc;
1023 usec_t t;
1024 int r;
1025
1026 assert(c);
1027
1028 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
1029 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
1030 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
1031 * any entropy. */
1032
1033 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
1034 if (errno != ENOENT)
1035 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
1036 } else {
1037 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
1038 return 0; /* Already done */
1039 }
1040
1041 t = now(CLOCK_MONOTONIC);
1042
1043 for (rps = random_pool_size(); rps > 0;) {
1044 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
1045
1046 rc = sym_Esys_GetRandom(
1047 c->esys_context,
1048 ESYS_TR_NONE,
1049 ESYS_TR_NONE,
1050 ESYS_TR_NONE,
1051 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1052 &buffer);
1053 if (rc != TSS2_RC_SUCCESS)
1054 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1055 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
1056
1057 if (buffer->size == 0)
1058 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1059 "Zero-sized entropy returned from TPM.");
1060
1061 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
1062 if (r < 0)
1063 return log_debug_errno(r, "Failed wo write entropy to kernel: %m");
1064
1065 done += buffer->size;
1066 rps = LESS_BY(rps, buffer->size);
1067 }
1068
1069 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
1070
1071 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
1072 if (r < 0)
1073 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
1074
1075 return 0;
1076 }
1077
1078 /* Get one of the legacy primary key templates.
1079 *
1080 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1081 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1082 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1083 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1084 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1085 /* Do not modify. */
1086 static const TPMT_PUBLIC legacy_ecc = {
1087 .type = TPM2_ALG_ECC,
1088 .nameAlg = TPM2_ALG_SHA256,
1089 .objectAttributes =
1090 TPMA_OBJECT_RESTRICTED|
1091 TPMA_OBJECT_DECRYPT|
1092 TPMA_OBJECT_FIXEDTPM|
1093 TPMA_OBJECT_FIXEDPARENT|
1094 TPMA_OBJECT_SENSITIVEDATAORIGIN|
1095 TPMA_OBJECT_USERWITHAUTH,
1096 .parameters.eccDetail = {
1097 .symmetric = {
1098 .algorithm = TPM2_ALG_AES,
1099 .keyBits.aes = 128,
1100 .mode.aes = TPM2_ALG_CFB,
1101 },
1102 .scheme.scheme = TPM2_ALG_NULL,
1103 .curveID = TPM2_ECC_NIST_P256,
1104 .kdf.scheme = TPM2_ALG_NULL,
1105 },
1106 };
1107
1108 /* Do not modify. */
1109 static const TPMT_PUBLIC legacy_rsa = {
1110 .type = TPM2_ALG_RSA,
1111 .nameAlg = TPM2_ALG_SHA256,
1112 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
1113 .parameters.rsaDetail = {
1114 .symmetric = {
1115 .algorithm = TPM2_ALG_AES,
1116 .keyBits.aes = 128,
1117 .mode.aes = TPM2_ALG_CFB,
1118 },
1119 .scheme.scheme = TPM2_ALG_NULL,
1120 .keyBits = 2048,
1121 },
1122 };
1123
1124 assert(ret_template);
1125
1126 if (alg == TPM2_ALG_ECC)
1127 *ret_template = legacy_ecc;
1128 else if (alg == TPM2_ALG_RSA)
1129 *ret_template = legacy_rsa;
1130 else
1131 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1132 "Unsupported legacy SRK alg: 0x%x", alg);
1133
1134 return 0;
1135 }
1136
1137 /* Get a Storage Root Key (SRK) template.
1138 *
1139 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1140 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1141 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1142 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1143 * "L-2" (for ECC).
1144 *
1145 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1146 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1147 *
1148 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1149 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1150 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1151 *
1152 * Returns 0 if the specified algorithm is ECC or RSA, otherwise -EOPNOTSUPP. */
1153 int tpm2_get_srk_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1154 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1155 * Provisioning Guidance document, specifically:
1156 * TPMA_OBJECT_USERWITHAUTH is added.
1157 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1158 * TPMA_OBJECT_NODA is added. */
1159 TPMA_OBJECT srk_attributes =
1160 TPMA_OBJECT_DECRYPT |
1161 TPMA_OBJECT_FIXEDPARENT |
1162 TPMA_OBJECT_FIXEDTPM |
1163 TPMA_OBJECT_NODA |
1164 TPMA_OBJECT_RESTRICTED |
1165 TPMA_OBJECT_SENSITIVEDATAORIGIN |
1166 TPMA_OBJECT_USERWITHAUTH;
1167
1168 /* The symmetric configuration is the same between ECC and RSA templates. */
1169 TPMT_SYM_DEF_OBJECT srk_symmetric = {
1170 .algorithm = TPM2_ALG_AES,
1171 .keyBits.aes = 128,
1172 .mode.aes = TPM2_ALG_CFB,
1173 };
1174
1175 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1176
1177 /* From the EK Credential Profile template "L-2". */
1178 TPMT_PUBLIC srk_ecc = {
1179 .type = TPM2_ALG_ECC,
1180 .nameAlg = TPM2_ALG_SHA256,
1181 .objectAttributes = srk_attributes,
1182 .parameters.eccDetail = {
1183 .symmetric = srk_symmetric,
1184 .scheme.scheme = TPM2_ALG_NULL,
1185 .curveID = TPM2_ECC_NIST_P256,
1186 .kdf.scheme = TPM2_ALG_NULL,
1187 },
1188 };
1189
1190 /* From the EK Credential Profile template "L-1". */
1191 TPMT_PUBLIC srk_rsa = {
1192 .type = TPM2_ALG_RSA,
1193 .nameAlg = TPM2_ALG_SHA256,
1194 .objectAttributes = srk_attributes,
1195 .parameters.rsaDetail = {
1196 .symmetric = srk_symmetric,
1197 .scheme.scheme = TPM2_ALG_NULL,
1198 .keyBits = 2048,
1199 },
1200 };
1201
1202 assert(ret_template);
1203
1204 switch (alg) {
1205 case TPM2_ALG_ECC:
1206 *ret_template = srk_ecc;
1207 return 0;
1208 case TPM2_ALG_RSA:
1209 *ret_template = srk_rsa;
1210 return 0;
1211 }
1212
1213 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "No SRK for algorithm 0x%" PRIx16, alg);
1214 }
1215
1216 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1217 int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template) {
1218 TPMT_PUBLIC template;
1219 int r;
1220
1221 assert(c);
1222 assert(ret_template);
1223
1224 r = tpm2_get_srk_template(TPM2_ALG_ECC, &template);
1225 if (r < 0)
1226 return r;
1227
1228 if (!tpm2_supports_alg(c, TPM2_ALG_ECC))
1229 log_debug("TPM does not support ECC.");
1230 else if (!tpm2_supports_ecc_curve(c, template.parameters.eccDetail.curveID))
1231 log_debug("TPM does not support ECC-NIST-P256 curve.");
1232 else if (!tpm2_supports_tpmt_public(c, &template))
1233 log_debug("TPM does not support SRK ECC template L-2.");
1234 else {
1235 *ret_template = template;
1236 return 0;
1237 }
1238
1239 r = tpm2_get_srk_template(TPM2_ALG_RSA, &template);
1240 if (r < 0)
1241 return r;
1242
1243 if (!tpm2_supports_alg(c, TPM2_ALG_RSA))
1244 log_debug("TPM does not support RSA.");
1245 else if (!tpm2_supports_tpmt_public(c, &template))
1246 log_debug("TPM does not support SRK RSA template L-1.");
1247 else {
1248 *ret_template = template;
1249 return 0;
1250 }
1251
1252 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1253 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1254 }
1255
1256 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1257 * tpm2_get_or_create_srk() below. */
1258 int tpm2_get_srk(
1259 Tpm2Context *c,
1260 const Tpm2Handle *session,
1261 TPM2B_PUBLIC **ret_public,
1262 TPM2B_NAME **ret_name,
1263 TPM2B_NAME **ret_qname,
1264 Tpm2Handle **ret_handle) {
1265
1266 return tpm2_index_to_handle(c, TPM2_SRK_HANDLE, session, ret_public, ret_name, ret_qname, ret_handle);
1267 }
1268
1269 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1270 * exists, or < 0 on error. */
1271 int tpm2_get_or_create_srk(
1272 Tpm2Context *c,
1273 const Tpm2Handle *session,
1274 TPM2B_PUBLIC **ret_public,
1275 TPM2B_NAME **ret_name,
1276 TPM2B_NAME **ret_qname,
1277 Tpm2Handle **ret_handle) {
1278
1279 int r;
1280
1281 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1282 if (r < 0)
1283 return r;
1284 if (r == 1)
1285 return 0; /* 0 → SRK already set up */
1286
1287 /* No SRK, create and persist one */
1288 TPM2B_PUBLIC template = {
1289 .size = sizeof(TPMT_PUBLIC),
1290 };
1291 r = tpm2_get_best_srk_template(c, &template.publicArea);
1292 if (r < 0)
1293 return log_debug_errno(r, "Could not get best SRK template: %m");
1294
1295 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
1296 r = tpm2_create_primary(
1297 c,
1298 session,
1299 &template,
1300 /* sensitive= */ NULL,
1301 /* ret_public= */ NULL,
1302 &transient_handle);
1303 if (r < 0)
1304 return r;
1305
1306 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1307 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1308 * either case, all threads will get the persistent SRK below. */
1309 r = tpm2_persist_handle(c, transient_handle, session, TPM2_SRK_HANDLE, /* ret_persistent_handle= */ NULL);
1310 if (r < 0)
1311 return r;
1312
1313 /* The SRK should exist now. */
1314 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1315 if (r < 0)
1316 return r;
1317 if (r == 0)
1318 /* This should never happen. */
1319 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SRK we just persisted couldn't be found.");
1320
1321 return 1; /* > 0 → SRK newly set up */
1322 }
1323
1324 /* Utility functions for TPMS_PCR_SELECTION. */
1325
1326 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1327 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s) {
1328 assert(s);
1329 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
1330
1331 uint32_t mask = 0;
1332 for (unsigned i = 0; i < s->sizeofSelect; i++)
1333 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
1334 return mask;
1335 }
1336
1337 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1338 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
1339 assert(ret);
1340
1341 /* This is currently hardcoded at 24 PCRs, above. */
1342 if (!TPM2_PCR_MASK_VALID(mask))
1343 log_debug("PCR mask selections (%x) out of range, ignoring.",
1344 mask & ~((uint32_t)TPM2_PCRS_MASK));
1345
1346 *ret = (TPMS_PCR_SELECTION){
1347 .hash = hash_alg,
1348 .sizeofSelect = TPM2_PCRS_MAX / 8,
1349 .pcrSelect[0] = mask & 0xff,
1350 .pcrSelect[1] = (mask >> 8) & 0xff,
1351 .pcrSelect[2] = (mask >> 16) & 0xff,
1352 };
1353 }
1354
1355 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1356 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION *s, uint32_t mask) {
1357 assert(s);
1358
1359 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s), mask);
1360 }
1361
1362 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION *s, uint32_t mask, bool b) {
1363 assert(s);
1364
1365 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s), mask, b), s->hash, s);
1366 }
1367
1368 /* Add all PCR selections in the mask. */
1369 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1370 tpm2_tpms_pcr_selection_update_mask(s, mask, 1);
1371 }
1372
1373 /* Remove all PCR selections in the mask. */
1374 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1375 tpm2_tpms_pcr_selection_update_mask(s, mask, 0);
1376 }
1377
1378 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1379 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1380 assert(a);
1381 assert(b);
1382 assert(a->hash == b->hash);
1383
1384 tpm2_tpms_pcr_selection_add_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1385 }
1386
1387 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1388 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1389 assert(a);
1390 assert(b);
1391 assert(a->hash == b->hash);
1392
1393 tpm2_tpms_pcr_selection_sub_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1394 }
1395
1396 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1397 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
1398 if (a == b)
1399 return;
1400
1401 tpm2_tpms_pcr_selection_add(a, b);
1402 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
1403 }
1404
1405 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1406 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1407 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1408 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1409 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1410
1411 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1412 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1413
1414 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1415 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1416 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1417
1418 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
1419 assert(s);
1420
1421 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
1422
1423 _cleanup_free_ char *mask = tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s));
1424 if (!mask)
1425 return NULL;
1426
1427 return strjoin(algstr, "(", mask, ")");
1428 }
1429
1430 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
1431 assert(s);
1432
1433 return popcount(tpm2_tpms_pcr_selection_to_mask(s));
1434 }
1435
1436 /* Utility functions for TPML_PCR_SELECTION. */
1437
1438 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1439 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
1440 assert(l);
1441 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1442 assert(index < l->count);
1443
1444 size_t s = l->count - (index + 1);
1445 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
1446 l->count--;
1447 }
1448
1449 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1450 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1451 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1452 static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1453 TPML_PCR_SELECTION *l,
1454 TPMI_ALG_HASH hash_alg) {
1455
1456 assert(l);
1457 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1458
1459 TPMS_PCR_SELECTION *selection = NULL;
1460 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1461 if (s->hash == hash_alg) {
1462 selection = s;
1463 break;
1464 }
1465
1466 if (!selection)
1467 return NULL;
1468
1469 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1470 for (uint32_t i = l->count - 1; i > 0; i--) {
1471 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
1472
1473 if (selection == s)
1474 break;
1475
1476 if (s->hash == hash_alg) {
1477 tpm2_tpms_pcr_selection_move(selection, s);
1478 tpm2_tpml_pcr_selection_remove_index(l, i);
1479 }
1480 }
1481
1482 return selection;
1483 }
1484
1485 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1486 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
1487 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1488 for (uint32_t i = 0; i < l->count; i++)
1489 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1490 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, l->pcrSelections[i].hash);
1491 }
1492
1493 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1494 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg) {
1495 assert(l);
1496
1497 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1498 * are multiple entries with the requested hash alg. */
1499 TPML_PCR_SELECTION lcopy = *l;
1500
1501 TPMS_PCR_SELECTION *s;
1502 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
1503 if (!s)
1504 return 0;
1505
1506 return tpm2_tpms_pcr_selection_to_mask(s);
1507 }
1508
1509 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1510 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
1511 assert(ret);
1512
1513 TPMS_PCR_SELECTION s;
1514 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
1515
1516 *ret = (TPML_PCR_SELECTION){
1517 .count = 1,
1518 .pcrSelections[0] = s,
1519 };
1520 }
1521
1522 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1523 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1524 * entries with the same hash alg. */
1525 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1526 assert(l);
1527 assert(s);
1528
1529 if (tpm2_tpms_pcr_selection_is_empty(s))
1530 return;
1531
1532 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1533 if (selection) {
1534 tpm2_tpms_pcr_selection_add(selection, s);
1535 return;
1536 }
1537
1538 /* It's already broken if the count is higher than the array has size for. */
1539 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1540
1541 /* If full, the cleanup should result in at least one available entry. */
1542 if (l->count == ELEMENTSOF(l->pcrSelections))
1543 tpm2_tpml_pcr_selection_cleanup(l);
1544
1545 assert(l->count < ELEMENTSOF(l->pcrSelections));
1546 l->pcrSelections[l->count++] = *s;
1547 }
1548
1549 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1550 * will combine all entries for 's->hash' in 'l'. */
1551 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1552 assert(l);
1553 assert(s);
1554
1555 if (tpm2_tpms_pcr_selection_is_empty(s))
1556 return;
1557
1558 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1559 if (selection)
1560 tpm2_tpms_pcr_selection_sub(selection, s);
1561 }
1562
1563 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1564 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1565 assert(l);
1566
1567 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l, hash), mask);
1568 }
1569
1570 /* Add the PCR selections in the mask, with the provided hash. */
1571 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1572 TPMS_PCR_SELECTION tpms;
1573
1574 assert(l);
1575
1576 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1577 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l, &tpms);
1578 }
1579
1580 /* Remove the PCR selections in the mask, with the provided hash. */
1581 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1582 TPMS_PCR_SELECTION tpms;
1583
1584 assert(l);
1585
1586 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1587 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l, &tpms);
1588 }
1589
1590 /* Add all PCR selections in 'b' to 'a'. */
1591 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1592 assert(a);
1593 assert(b);
1594
1595 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1596 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
1597 }
1598
1599 /* Remove all PCR selections in 'b' from 'a'. */
1600 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1601 assert(a);
1602 assert(b);
1603
1604 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1605 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
1606 }
1607
1608 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
1609 assert(l);
1610
1611 _cleanup_free_ char *banks = NULL;
1612 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1613 if (tpm2_tpms_pcr_selection_is_empty(s))
1614 continue;
1615
1616 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
1617 if (!str || !strextend_with_separator(&banks, ",", str))
1618 return NULL;
1619 }
1620
1621 return strjoin("[", strempty(banks), "]");
1622 }
1623
1624 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
1625 assert(l);
1626 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1627
1628 size_t weight = 0;
1629 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1630 size_t w = tpm2_tpms_pcr_selection_weight(s);
1631 assert(weight <= SIZE_MAX - w);
1632 weight += w;
1633 }
1634
1635 return weight;
1636 }
1637
1638 bool tpm2_pcr_value_valid(const Tpm2PCRValue *pcr_value) {
1639 int r;
1640
1641 if (!pcr_value)
1642 return false;
1643
1644 if (!TPM2_PCR_INDEX_VALID(pcr_value->index)) {
1645 log_debug("PCR index %u invalid.", pcr_value->index);
1646 return false;
1647 }
1648
1649 /* If it contains a value, the value size must match the hash size. */
1650 if (pcr_value->value.size > 0) {
1651 r = tpm2_hash_alg_to_size(pcr_value->hash);
1652 if (r < 0)
1653 return false;
1654
1655 if (pcr_value->value.size != (size_t) r) {
1656 log_debug("PCR hash 0x%" PRIx16 " expected size %d does not match actual size %" PRIu16 ".",
1657 pcr_value->hash, r, pcr_value->value.size);
1658 return false;
1659 }
1660 }
1661
1662 return true;
1663 }
1664
1665 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1666 *
1667 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1668 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1669 *
1670 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1671 */
1672 bool tpm2_pcr_values_valid(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1673 if (!pcr_values && n_pcr_values > 0)
1674 return false;
1675
1676 const Tpm2PCRValue *previous = NULL;
1677 FOREACH_ARRAY(current, pcr_values, n_pcr_values) {
1678 if (!tpm2_pcr_value_valid(current))
1679 return false;
1680
1681 if (!previous) {
1682 previous = current;
1683 continue;
1684 }
1685
1686 /* Hashes must be sorted in ascending order */
1687 if (current->hash < previous->hash) {
1688 log_debug("PCR values not in ascending order, hash %" PRIu16 " is after %" PRIu16 ".",
1689 current->hash, previous->hash);
1690 return false;
1691 }
1692
1693 if (current->hash == previous->hash) {
1694 /* Indexes (for the same hash) must be sorted in ascending order */
1695 if (current->index < previous->index) {
1696 log_debug("PCR values not in ascending order, hash %" PRIu16 " index %u is after %u.",
1697 current->hash, current->index, previous->index);
1698 return false;
1699 }
1700
1701 /* Indexes (for the same hash) must not be duplicates */
1702 if (current->index == previous->index) {
1703 log_debug("PCR values contain duplicates for hash %" PRIu16 " index %u.",
1704 current->hash, previous->index);
1705 return false;
1706 }
1707 }
1708 }
1709
1710 return true;
1711 }
1712
1713 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1714 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1715 assert(pcr_values || n_pcr_values == 0);
1716
1717 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1718 if (v->value.size > 0)
1719 return true;
1720
1721 return false;
1722 }
1723
1724 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1725 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1726 assert(pcr_values || n_pcr_values == 0);
1727
1728 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1729 if (v->value.size == 0)
1730 return false;
1731
1732 return true;
1733 }
1734
1735 static int cmp_pcr_values(const Tpm2PCRValue *a, const Tpm2PCRValue *b) {
1736 assert(a);
1737 assert(b);
1738
1739 return CMP(a->hash, b->hash) ?: CMP(a->index, b->index);
1740 }
1741
1742 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1743 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1744 void tpm2_sort_pcr_values(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1745 typesafe_qsort(pcr_values, n_pcr_values, cmp_pcr_values);
1746 }
1747
1748 int tpm2_pcr_values_from_mask(uint32_t mask, TPMI_ALG_HASH hash, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1749 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1750 size_t n_pcr_values = 0;
1751
1752 assert(ret_pcr_values);
1753 assert(ret_n_pcr_values);
1754
1755 FOREACH_PCR_IN_MASK(index, mask)
1756 if (!GREEDY_REALLOC_APPEND(
1757 pcr_values,
1758 n_pcr_values,
1759 &TPM2_PCR_VALUE_MAKE(index, hash, {}),
1760 1))
1761 return log_oom_debug();
1762
1763 *ret_pcr_values = TAKE_PTR(pcr_values);
1764 *ret_n_pcr_values = n_pcr_values;
1765
1766 return 0;
1767 }
1768
1769 int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPMI_ALG_HASH hash, uint32_t *ret_mask) {
1770 uint32_t mask = 0;
1771
1772 assert(pcr_values || n_pcr_values == 0);
1773 assert(ret_mask);
1774
1775 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1776 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PCR values.");
1777
1778 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1779 if (v->hash == hash)
1780 SET_BIT(mask, v->index);
1781
1782 *ret_mask = mask;
1783
1784 return 0;
1785 }
1786
1787 int tpm2_tpml_pcr_selection_from_pcr_values(
1788 const Tpm2PCRValue *pcr_values,
1789 size_t n_pcr_values,
1790 TPML_PCR_SELECTION *ret_selection,
1791 TPM2B_DIGEST **ret_values,
1792 size_t *ret_n_values) {
1793
1794 TPML_PCR_SELECTION selection = {};
1795 _cleanup_free_ TPM2B_DIGEST *values = NULL;
1796 size_t n_values = 0;
1797
1798 assert(pcr_values || n_pcr_values == 0);
1799
1800 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1801 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "PCR values are not valid.");
1802
1803 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1804 tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
1805
1806 if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
1807 return log_oom_debug();
1808 }
1809
1810 if (ret_selection)
1811 *ret_selection = selection;
1812 if (ret_values)
1813 *ret_values = TAKE_PTR(values);
1814 if (ret_n_values)
1815 *ret_n_values = n_values;
1816
1817 return 0;
1818 }
1819
1820 /* Count the number of different hash algorithms for all the entries. */
1821 int tpm2_pcr_values_hash_count(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, size_t *ret_count) {
1822 TPML_PCR_SELECTION selection;
1823 int r;
1824
1825 assert(pcr_values);
1826 assert(ret_count);
1827
1828 r = tpm2_tpml_pcr_selection_from_pcr_values(
1829 pcr_values,
1830 n_pcr_values,
1831 &selection,
1832 /* ret_values= */ NULL,
1833 /* ret_n_values= */ NULL);
1834 if (r < 0)
1835 return r;
1836
1837 *ret_count = selection.count;
1838
1839 return 0;
1840 }
1841
1842 /* Parse a string argument into a Tpm2PCRValue object.
1843 *
1844 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1845 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1846 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1847 int tpm2_pcr_value_from_string(const char *arg, Tpm2PCRValue *ret_pcr_value) {
1848 Tpm2PCRValue pcr_value = {};
1849 const char *p = arg;
1850 int r;
1851
1852 assert(arg);
1853 assert(ret_pcr_value);
1854
1855 _cleanup_free_ char *index = NULL;
1856 r = extract_first_word(&p, &index, ":", /* flags= */ 0);
1857 if (r < 1)
1858 return log_debug_errno(r, "Could not parse pcr value '%s': %m", p);
1859
1860 r = tpm2_pcr_index_from_string(index);
1861 if (r < 0)
1862 return log_debug_errno(r, "Invalid pcr index '%s': %m", index);
1863 pcr_value.index = (unsigned) r;
1864
1865 if (!isempty(p)) {
1866 _cleanup_free_ char *hash = NULL;
1867 r = extract_first_word(&p, &hash, "=", /* flags= */ 0);
1868 if (r < 1)
1869 return log_debug_errno(r, "Could not parse pcr hash algorithm '%s': %m", p);
1870
1871 r = tpm2_hash_alg_from_string(hash);
1872 if (r < 0)
1873 return log_debug_errno(r, "Invalid pcr hash algorithm '%s': %m", hash);
1874 pcr_value.hash = (TPMI_ALG_HASH) r;
1875
1876 if (!isempty(p)) {
1877 /* Remove leading 0x if present */
1878 p = startswith_no_case(p, "0x") ?: p;
1879
1880 _cleanup_free_ void *buf = NULL;
1881 size_t buf_size = 0;
1882 r = unhexmem(p, &buf, &buf_size);
1883 if (r < 0)
1884 return log_debug_errno(r, "Invalid pcr hash value '%s': %m", p);
1885
1886 r = TPM2B_DIGEST_CHECK_SIZE(buf_size);
1887 if (r < 0)
1888 return log_debug_errno(r, "PCR hash value size %zu too large.", buf_size);
1889
1890 pcr_value.value = TPM2B_DIGEST_MAKE(buf, buf_size);
1891 }
1892 }
1893
1894 *ret_pcr_value = pcr_value;
1895
1896 return 0;
1897 }
1898
1899 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1900 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1901 * string. This does not check for validity. */
1902 char *tpm2_pcr_value_to_string(const Tpm2PCRValue *pcr_value) {
1903 _cleanup_free_ char *index = NULL, *value = NULL;
1904
1905 if (asprintf(&index, "%u", pcr_value->index) < 0)
1906 return NULL;
1907
1908 const char *hash = pcr_value->hash > 0 ? tpm2_hash_alg_to_string(pcr_value->hash) : NULL;
1909
1910 if (hash && pcr_value->value.size > 0) {
1911 value = hexmem(pcr_value->value.buffer, pcr_value->value.size);
1912 if (!value)
1913 return NULL;
1914 }
1915
1916 return strjoin(index, hash ? ":" : "", strempty(hash), value ? "=" : "", strempty(value));
1917 }
1918
1919 /* Parse a string argument into an array of Tpm2PCRValue objects.
1920 *
1921 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1922 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1923 int tpm2_pcr_values_from_string(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1924 const char *p = arg;
1925 int r;
1926
1927 assert(arg);
1928 assert(ret_pcr_values);
1929 assert(ret_n_pcr_values);
1930
1931 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1932 size_t n_pcr_values = 0;
1933
1934 for (;;) {
1935 _cleanup_free_ char *pcr_arg = NULL;
1936 r = extract_first_word(&p, &pcr_arg, ",+", /* flags= */ 0);
1937 if (r < 0)
1938 return log_debug_errno(r, "Could not parse pcr values '%s': %m", p);
1939 if (r == 0)
1940 break;
1941
1942 Tpm2PCRValue pcr_value;
1943 r = tpm2_pcr_value_from_string(pcr_arg, &pcr_value);
1944 if (r < 0)
1945 return r;
1946
1947 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
1948 return log_oom_debug();
1949 }
1950
1951 *ret_pcr_values = TAKE_PTR(pcr_values);
1952 *ret_n_pcr_values = n_pcr_values;
1953
1954 return 0;
1955 }
1956
1957 /* Return a string representing the array of PCR values. The format is as described in
1958 * tpm2_pcr_values_from_string(). This does not check for validity. */
1959 char *tpm2_pcr_values_to_string(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1960 _cleanup_free_ char *s = NULL;
1961
1962 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1963 _cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(v);
1964 if (!pcrstr || !strextend_with_separator(&s, "+", pcrstr))
1965 return NULL;
1966 }
1967
1968 return s ? TAKE_PTR(s) : strdup("");
1969 }
1970
1971 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
1972 if (!DEBUG_LOGGING || !l)
1973 return;
1974
1975 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
1976 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
1977 }
1978
1979 void tpm2_log_debug_pcr_value(const Tpm2PCRValue *pcr_value, const char *msg) {
1980 if (!DEBUG_LOGGING || !pcr_value)
1981 return;
1982
1983 _cleanup_free_ char *s = tpm2_pcr_value_to_string(pcr_value);
1984 log_debug("%s: %s", msg ?: "PCR value", strna(s));
1985 }
1986
1987 void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
1988 if (!DEBUG_LOGGING || !buffer || size == 0)
1989 return;
1990
1991 _cleanup_free_ char *h = hexmem(buffer, size);
1992 log_debug("%s: %s", msg ?: "Buffer", strna(h));
1993 }
1994
1995 void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
1996 if (digest)
1997 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
1998 }
1999
2000 void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
2001 if (name)
2002 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
2003 }
2004
2005 static int tpm2_get_policy_digest(
2006 Tpm2Context *c,
2007 const Tpm2Handle *session,
2008 TPM2B_DIGEST **ret_policy_digest) {
2009
2010 TSS2_RC rc;
2011
2012 if (!DEBUG_LOGGING && !ret_policy_digest)
2013 return 0;
2014
2015 assert(c);
2016 assert(session);
2017
2018 log_debug("Acquiring policy digest.");
2019
2020 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
2021 rc = sym_Esys_PolicyGetDigest(
2022 c->esys_context,
2023 session->esys_handle,
2024 ESYS_TR_NONE,
2025 ESYS_TR_NONE,
2026 ESYS_TR_NONE,
2027 &policy_digest);
2028 if (rc != TSS2_RC_SUCCESS)
2029 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2030 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
2031
2032 tpm2_log_debug_digest(policy_digest, "Session policy digest");
2033
2034 if (ret_policy_digest)
2035 *ret_policy_digest = TAKE_PTR(policy_digest);
2036
2037 return 0;
2038 }
2039
2040 int tpm2_create_primary(
2041 Tpm2Context *c,
2042 const Tpm2Handle *session,
2043 const TPM2B_PUBLIC *template,
2044 const TPM2B_SENSITIVE_CREATE *sensitive,
2045 TPM2B_PUBLIC **ret_public,
2046 Tpm2Handle **ret_handle) {
2047
2048 usec_t ts;
2049 TSS2_RC rc;
2050 int r;
2051
2052 assert(c);
2053 assert(template);
2054
2055 log_debug("Creating primary key on TPM.");
2056
2057 ts = now(CLOCK_MONOTONIC);
2058
2059 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2060 r = tpm2_handle_new(c, &handle);
2061 if (r < 0)
2062 return r;
2063
2064 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2065 rc = sym_Esys_CreatePrimary(
2066 c->esys_context,
2067 ESYS_TR_RH_OWNER,
2068 session ? session->esys_handle : ESYS_TR_PASSWORD,
2069 ESYS_TR_NONE,
2070 ESYS_TR_NONE,
2071 sensitive ?: &(TPM2B_SENSITIVE_CREATE) {},
2072 template,
2073 /* outsideInfo= */ NULL,
2074 &(TPML_PCR_SELECTION) {},
2075 &handle->esys_handle,
2076 &public,
2077 /* creationData= */ NULL,
2078 /* creationHash= */ NULL,
2079 /* creationTicket= */ NULL);
2080 if (rc != TSS2_RC_SUCCESS)
2081 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2082 "Failed to generate primary key in TPM: %s",
2083 sym_Tss2_RC_Decode(rc));
2084
2085 log_debug("Successfully created primary key on TPM in %s.",
2086 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2087
2088 if (ret_public)
2089 *ret_public = TAKE_PTR(public);
2090 if (ret_handle)
2091 *ret_handle = TAKE_PTR(handle);
2092
2093 return 0;
2094 }
2095
2096 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2097 * instead use tpm2_create_primary(). */
2098 int tpm2_create(Tpm2Context *c,
2099 const Tpm2Handle *parent,
2100 const Tpm2Handle *session,
2101 const TPMT_PUBLIC *template,
2102 const TPMS_SENSITIVE_CREATE *sensitive,
2103 TPM2B_PUBLIC **ret_public,
2104 TPM2B_PRIVATE **ret_private) {
2105
2106 usec_t ts;
2107 TSS2_RC rc;
2108
2109 assert(c);
2110 assert(parent);
2111 assert(template);
2112
2113 log_debug("Creating object on TPM.");
2114
2115 ts = now(CLOCK_MONOTONIC);
2116
2117 TPM2B_PUBLIC tpm2b_public = {
2118 .size = sizeof(*template) - sizeof(template->unique),
2119 .publicArea = *template,
2120 };
2121
2122 /* Zero the unique area. */
2123 zero(tpm2b_public.publicArea.unique);
2124
2125 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2126 if (sensitive)
2127 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2128 .size = sizeof(*sensitive),
2129 .sensitive = *sensitive,
2130 };
2131 else
2132 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2133
2134 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2135 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2136 rc = sym_Esys_Create(
2137 c->esys_context,
2138 parent->esys_handle,
2139 session ? session->esys_handle : ESYS_TR_PASSWORD,
2140 ESYS_TR_NONE,
2141 ESYS_TR_NONE,
2142 &tpm2b_sensitive,
2143 &tpm2b_public,
2144 /* outsideInfo= */ NULL,
2145 &(TPML_PCR_SELECTION) {},
2146 &private,
2147 &public,
2148 /* creationData= */ NULL,
2149 /* creationHash= */ NULL,
2150 /* creationTicket= */ NULL);
2151 if (rc != TSS2_RC_SUCCESS)
2152 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2153 "Failed to generate object in TPM: %s",
2154 sym_Tss2_RC_Decode(rc));
2155
2156 log_debug("Successfully created object on TPM in %s.",
2157 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2158
2159 if (ret_public)
2160 *ret_public = TAKE_PTR(public);
2161 if (ret_private)
2162 *ret_private = TAKE_PTR(private);
2163
2164 return 0;
2165 }
2166
2167 int tpm2_load(
2168 Tpm2Context *c,
2169 const Tpm2Handle *parent,
2170 const Tpm2Handle *session,
2171 const TPM2B_PUBLIC *public,
2172 const TPM2B_PRIVATE *private,
2173 Tpm2Handle **ret_handle) {
2174
2175 TSS2_RC rc;
2176 int r;
2177
2178 assert(c);
2179 assert(public);
2180 assert(private);
2181 assert(ret_handle);
2182
2183 log_debug("Loading object into TPM.");
2184
2185 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2186 r = tpm2_handle_new(c, &handle);
2187 if (r < 0)
2188 return r;
2189
2190 rc = sym_Esys_Load(
2191 c->esys_context,
2192 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
2193 session ? session->esys_handle : ESYS_TR_PASSWORD,
2194 ESYS_TR_NONE,
2195 ESYS_TR_NONE,
2196 private,
2197 public,
2198 &handle->esys_handle);
2199 if (rc == TPM2_RC_LOCKOUT)
2200 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK),
2201 "TPM2 device is in dictionary attack lockout mode.");
2202 if (rc != TSS2_RC_SUCCESS)
2203 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2204 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc));
2205
2206 *ret_handle = TAKE_PTR(handle);
2207
2208 return 0;
2209 }
2210
2211 static int tpm2_load_external(
2212 Tpm2Context *c,
2213 const Tpm2Handle *session,
2214 const TPM2B_PUBLIC *public,
2215 const TPM2B_SENSITIVE *private,
2216 Tpm2Handle **ret_handle) {
2217
2218 TSS2_RC rc;
2219 int r;
2220
2221 assert(c);
2222 assert(ret_handle);
2223
2224 log_debug("Loading external key into TPM.");
2225
2226 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2227 r = tpm2_handle_new(c, &handle);
2228 if (r < 0)
2229 return r;
2230
2231 rc = sym_Esys_LoadExternal(
2232 c->esys_context,
2233 session ? session->esys_handle : ESYS_TR_NONE,
2234 ESYS_TR_NONE,
2235 ESYS_TR_NONE,
2236 private,
2237 public,
2238 #if HAVE_TSS2_ESYS3
2239 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2240 * hierarchy, older versions need TPM2_RH_* instead. */
2241 ESYS_TR_RH_OWNER,
2242 #else
2243 TPM2_RH_OWNER,
2244 #endif
2245 &handle->esys_handle);
2246 if (rc != TSS2_RC_SUCCESS)
2247 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2248 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
2249
2250 *ret_handle = TAKE_PTR(handle);
2251
2252 return 0;
2253 }
2254
2255 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2256 * use tpm2_create_loaded(). */
2257 static int _tpm2_create_loaded(
2258 Tpm2Context *c,
2259 const Tpm2Handle *parent,
2260 const Tpm2Handle *session,
2261 const TPMT_PUBLIC *template,
2262 const TPMS_SENSITIVE_CREATE *sensitive,
2263 TPM2B_PUBLIC **ret_public,
2264 TPM2B_PRIVATE **ret_private,
2265 Tpm2Handle **ret_handle) {
2266
2267 usec_t ts;
2268 TSS2_RC rc;
2269 int r;
2270
2271 assert(c);
2272 assert(parent);
2273 assert(template);
2274
2275 log_debug("Creating loaded object on TPM.");
2276
2277 ts = now(CLOCK_MONOTONIC);
2278
2279 /* Copy the input template and zero the unique area. */
2280 TPMT_PUBLIC template_copy = *template;
2281 zero(template_copy.unique);
2282
2283 TPM2B_TEMPLATE tpm2b_template;
2284 size_t size = 0;
2285 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2286 &template_copy,
2287 tpm2b_template.buffer,
2288 sizeof(tpm2b_template.buffer),
2289 &size);
2290 if (rc != TSS2_RC_SUCCESS)
2291 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2292 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc));
2293 assert(size <= UINT16_MAX);
2294 tpm2b_template.size = size;
2295
2296 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2297 if (sensitive)
2298 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2299 .size = sizeof(*sensitive),
2300 .sensitive = *sensitive,
2301 };
2302 else
2303 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2304
2305 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2306 r = tpm2_handle_new(c, &handle);
2307 if (r < 0)
2308 return r;
2309
2310 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2311 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2312 rc = sym_Esys_CreateLoaded(
2313 c->esys_context,
2314 parent->esys_handle,
2315 session ? session->esys_handle : ESYS_TR_PASSWORD,
2316 ESYS_TR_NONE,
2317 ESYS_TR_NONE,
2318 &tpm2b_sensitive,
2319 &tpm2b_template,
2320 &handle->esys_handle,
2321 &private,
2322 &public);
2323 if (rc != TSS2_RC_SUCCESS)
2324 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2325 "Failed to generate loaded object in TPM: %s",
2326 sym_Tss2_RC_Decode(rc));
2327
2328 log_debug("Successfully created loaded object on TPM in %s.",
2329 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2330
2331 if (ret_public)
2332 *ret_public = TAKE_PTR(public);
2333 if (ret_private)
2334 *ret_private = TAKE_PTR(private);
2335 if (ret_handle)
2336 *ret_handle = TAKE_PTR(handle);
2337
2338 return 0;
2339 }
2340
2341 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2342 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2343 * tpm2_create_primary(). */
2344 int tpm2_create_loaded(
2345 Tpm2Context *c,
2346 const Tpm2Handle *parent,
2347 const Tpm2Handle *session,
2348 const TPMT_PUBLIC *template,
2349 const TPMS_SENSITIVE_CREATE *sensitive,
2350 TPM2B_PUBLIC **ret_public,
2351 TPM2B_PRIVATE **ret_private,
2352 Tpm2Handle **ret_handle) {
2353
2354 int r;
2355
2356 if (tpm2_supports_command(c, TPM2_CC_CreateLoaded))
2357 return _tpm2_create_loaded(c, parent, session, template, sensitive, ret_public, ret_private, ret_handle);
2358
2359 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2360 * create and load manually. */
2361 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2362 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2363 r = tpm2_create(c, parent, session, template, sensitive, &public, &private);
2364 if (r < 0)
2365 return r;
2366
2367 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2368 r = tpm2_load(c, parent, session, public, private, &handle);
2369 if (r < 0)
2370 return r;
2371
2372 if (ret_public)
2373 *ret_public = TAKE_PTR(public);
2374 if (ret_private)
2375 *ret_private = TAKE_PTR(private);
2376 if (ret_handle)
2377 *ret_handle = TAKE_PTR(handle);
2378
2379 return 0;
2380 }
2381
2382 static int tpm2_marshal_private(const TPM2B_PRIVATE *private, void **ret, size_t *ret_size) {
2383 size_t max_size = sizeof(*private), blob_size = 0;
2384 _cleanup_free_ void *blob = NULL;
2385 TSS2_RC rc;
2386
2387 assert(private);
2388 assert(ret);
2389 assert(ret_size);
2390
2391 blob = malloc0(max_size);
2392 if (!blob)
2393 return log_oom_debug();
2394
2395 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
2396 if (rc != TSS2_RC_SUCCESS)
2397 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2398 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
2399
2400 *ret = TAKE_PTR(blob);
2401 *ret_size = blob_size;
2402 return 0;
2403 }
2404
2405 static int tpm2_unmarshal_private(const void *data, size_t size, TPM2B_PRIVATE *ret_private) {
2406 TPM2B_PRIVATE private = {};
2407 size_t offset = 0;
2408 TSS2_RC rc;
2409
2410 assert(data || size == 0);
2411 assert(ret_private);
2412
2413 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(data, size, &offset, &private);
2414 if (rc != TSS2_RC_SUCCESS)
2415 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2416 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
2417 if (offset != size)
2418 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2419 "Garbage at end of private key marshal data.");
2420
2421 *ret_private = private;
2422 return 0;
2423 }
2424
2425 int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size) {
2426 size_t max_size = sizeof(*public), blob_size = 0;
2427 _cleanup_free_ void *blob = NULL;
2428 TSS2_RC rc;
2429
2430 assert(public);
2431 assert(ret);
2432 assert(ret_size);
2433
2434 blob = malloc0(max_size);
2435 if (!blob)
2436 return log_oom_debug();
2437
2438 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
2439 if (rc != TSS2_RC_SUCCESS)
2440 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2441 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
2442
2443 *ret = TAKE_PTR(blob);
2444 *ret_size = blob_size;
2445 return 0;
2446 }
2447
2448 static int tpm2_unmarshal_public(const void *data, size_t size, TPM2B_PUBLIC *ret_public) {
2449 TPM2B_PUBLIC public = {};
2450 size_t offset = 0;
2451 TSS2_RC rc;
2452
2453 assert(data || size == 0);
2454 assert(ret_public);
2455
2456 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(data, size, &offset, &public);
2457 if (rc != TSS2_RC_SUCCESS)
2458 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2459 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
2460 if (offset != size)
2461 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2462 "Garbage at end of public key marshal data.");
2463
2464 *ret_public = public;
2465 return 0;
2466 }
2467
2468 int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC *nv_public, void **ret, size_t *ret_size) {
2469 size_t max_size = sizeof(*nv_public), blob_size = 0;
2470 _cleanup_free_ void *blob = NULL;
2471 TSS2_RC rc;
2472
2473 assert(nv_public);
2474 assert(ret);
2475 assert(ret_size);
2476
2477 blob = malloc0(max_size);
2478 if (!blob)
2479 return log_oom_debug();
2480
2481 rc = sym_Tss2_MU_TPM2B_NV_PUBLIC_Marshal(nv_public, blob, max_size, &blob_size);
2482 if (rc != TSS2_RC_SUCCESS)
2483 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2484 "Failed to marshal NV public structure: %s", sym_Tss2_RC_Decode(rc));
2485
2486 *ret = TAKE_PTR(blob);
2487 *ret_size = blob_size;
2488 return 0;
2489 }
2490
2491 int tpm2_unmarshal_nv_public(const void *data, size_t size, TPM2B_NV_PUBLIC *ret_nv_public) {
2492 TPM2B_NV_PUBLIC nv_public = {};
2493 size_t offset = 0;
2494 TSS2_RC rc;
2495
2496 assert(data || size == 0);
2497 assert(ret_nv_public);
2498
2499 rc = sym_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal(data, size, &offset, &nv_public);
2500 if (rc != TSS2_RC_SUCCESS)
2501 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2502 "Failed to unmarshal NV public structure: %s", sym_Tss2_RC_Decode(rc));
2503 if (offset != size)
2504 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2505 "Garbage at end of NV public structure marshal data.");
2506
2507 *ret_nv_public = nv_public;
2508 return 0;
2509 }
2510
2511 static int tpm2_import(
2512 Tpm2Context *c,
2513 const Tpm2Handle *parent,
2514 const Tpm2Handle *session,
2515 const TPM2B_PUBLIC *public,
2516 const TPM2B_PRIVATE *private,
2517 const TPM2B_ENCRYPTED_SECRET *seed,
2518 const TPM2B_DATA *encryption_key,
2519 const TPMT_SYM_DEF_OBJECT *symmetric,
2520 TPM2B_PRIVATE **ret_private) {
2521
2522 TSS2_RC rc;
2523
2524 assert(c);
2525 assert(parent);
2526 assert(!!encryption_key == !!symmetric);
2527 assert(public);
2528 assert(private);
2529 assert(seed);
2530 assert(ret_private);
2531
2532 log_debug("Importing key into TPM.");
2533
2534 rc = sym_Esys_Import(
2535 c->esys_context,
2536 parent->esys_handle,
2537 session ? session->esys_handle : ESYS_TR_PASSWORD,
2538 ESYS_TR_NONE,
2539 ESYS_TR_NONE,
2540 encryption_key,
2541 public,
2542 private,
2543 seed,
2544 symmetric ?: &(TPMT_SYM_DEF_OBJECT){ .algorithm = TPM2_ALG_NULL, },
2545 ret_private);
2546 if (rc != TSS2_RC_SUCCESS)
2547 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2548 "Failed to import key into TPM: %s", sym_Tss2_RC_Decode(rc));
2549
2550 return 0;
2551 }
2552
2553 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2554 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2555 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2556 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2557 * values. */
2558 int tpm2_pcr_read(
2559 Tpm2Context *c,
2560 const TPML_PCR_SELECTION *pcr_selection,
2561 Tpm2PCRValue **ret_pcr_values,
2562 size_t *ret_n_pcr_values) {
2563
2564 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2565 size_t n_pcr_values = 0;
2566 TSS2_RC rc;
2567
2568 assert(c);
2569 assert(pcr_selection);
2570 assert(ret_pcr_values);
2571 assert(ret_n_pcr_values);
2572
2573 TPML_PCR_SELECTION remaining = *pcr_selection;
2574 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
2575 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
2576 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
2577
2578 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
2579
2580 /* Unfortunately, PCR_Read will not return more than 8 values. */
2581 rc = sym_Esys_PCR_Read(
2582 c->esys_context,
2583 ESYS_TR_NONE,
2584 ESYS_TR_NONE,
2585 ESYS_TR_NONE,
2586 &remaining,
2587 NULL,
2588 &current_read,
2589 &current_values);
2590 if (rc != TSS2_RC_SUCCESS)
2591 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2592 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
2593
2594 tpm2_log_debug_tpml_pcr_selection(current_read, "Read PCR selection");
2595
2596 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
2597 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2598 break;
2599 }
2600
2601 unsigned i = 0;
2602 FOREACH_PCR_IN_TPML_PCR_SELECTION(index, tpms, current_read) {
2603 assert(i < current_values->count);
2604 Tpm2PCRValue pcr_value = {
2605 .index = index,
2606 .hash = tpms->hash,
2607 .value = current_values->digests[i++],
2608 };
2609
2610 tpm2_log_debug_pcr_value(&pcr_value, /* msg= */ NULL);
2611
2612 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
2613 return log_oom_debug();
2614 }
2615 assert(i == current_values->count);
2616
2617 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
2618 }
2619
2620 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
2621
2622 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
2623 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PCR values read from TPM are not valid.");
2624
2625 *ret_pcr_values = TAKE_PTR(pcr_values);
2626 *ret_n_pcr_values = n_pcr_values;
2627
2628 return 0;
2629 }
2630
2631 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2632 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2633 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2634 * appropriate entries, this returns an error. This does not check the array for validity. */
2635 int tpm2_pcr_read_missing_values(Tpm2Context *c, Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
2636 TPMI_ALG_HASH pcr_bank = 0;
2637 int r;
2638
2639 assert(c);
2640 assert(pcr_values || n_pcr_values == 0);
2641
2642 if (n_pcr_values > 0) {
2643 size_t hash_count;
2644 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
2645 if (r < 0)
2646 return log_debug_errno(r, "Could not get hash count from pcr values: %m");
2647
2648 if (hash_count == 1 && pcr_values[0].hash == 0) {
2649 uint32_t mask;
2650 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, 0, &mask);
2651 if (r < 0)
2652 return r;
2653
2654 r = tpm2_get_best_pcr_bank(c, mask, &pcr_bank);
2655 if (r < 0)
2656 return r;
2657 }
2658 }
2659
2660 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
2661 if (v->hash == 0)
2662 v->hash = pcr_bank;
2663
2664 if (v->value.size > 0)
2665 continue;
2666
2667 TPML_PCR_SELECTION selection;
2668 r = tpm2_tpml_pcr_selection_from_pcr_values(v, 1, &selection, NULL, NULL);
2669 if (r < 0)
2670 return r;
2671
2672 _cleanup_free_ Tpm2PCRValue *read_values = NULL;
2673 size_t n_read_values;
2674 r = tpm2_pcr_read(c, &selection, &read_values, &n_read_values);
2675 if (r < 0)
2676 return r;
2677
2678 if (n_read_values == 0)
2679 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2680 "Could not read PCR hash 0x%" PRIu16 " index %u",
2681 v->hash, v->index);
2682
2683 assert(n_read_values == 1);
2684 assert(read_values[0].hash == v->hash);
2685 assert(read_values[0].index == v->index);
2686
2687 v->value = read_values[0].value;
2688 }
2689
2690 return 0;
2691 }
2692
2693 static int tpm2_pcr_mask_good(
2694 Tpm2Context *c,
2695 TPMI_ALG_HASH bank,
2696 uint32_t mask) {
2697
2698 TPML_PCR_SELECTION selection;
2699 int r;
2700
2701 assert(c);
2702
2703 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2704 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2705 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2706
2707 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
2708
2709 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2710 size_t n_pcr_values;
2711 r = tpm2_pcr_read(c, &selection, &pcr_values, &n_pcr_values);
2712 if (r < 0)
2713 return r;
2714
2715 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2716 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
2717 if (!memeqbyte(0x00, v->value.buffer, v->value.size) &&
2718 !memeqbyte(0xFF, v->value.buffer, v->value.size))
2719 return true;
2720
2721 return false;
2722 }
2723
2724 static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
2725
2726 assert(selection);
2727
2728 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2729 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2730 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
2731 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2732 strna(tpm2_hash_alg_to_string(selection->hash)));
2733 return false;
2734 }
2735
2736 assert_cc(TPM2_PCRS_MAX % 8 == 0);
2737
2738 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2739 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2740 bool valid = true;
2741 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
2742 if (selection->pcrSelect[j] != 0xFF) {
2743 valid = false;
2744 break;
2745 }
2746
2747 if (!valid)
2748 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2749 strna(tpm2_hash_alg_to_string(selection->hash)));
2750
2751 return valid;
2752 }
2753
2754 int tpm2_get_best_pcr_bank(
2755 Tpm2Context *c,
2756 uint32_t pcr_mask,
2757 TPMI_ALG_HASH *ret) {
2758
2759 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
2760 int r;
2761
2762 assert(c);
2763 assert(ret);
2764
2765 if (pcr_mask == 0) {
2766 log_debug("Asked to pick best PCR bank but no PCRs selected we could derive this from. Defaulting to SHA256.");
2767 *ret = TPM2_ALG_SHA256; /* if no PCRs are selected this doesn't matter anyway... */
2768 return 0;
2769 }
2770
2771 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2772 TPMI_ALG_HASH hash = selection->hash;
2773 int good;
2774
2775 /* For now we are only interested in the SHA1 and SHA256 banks */
2776 if (!IN_SET(hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
2777 continue;
2778
2779 r = tpm2_bank_has24(selection);
2780 if (r < 0)
2781 return r;
2782 if (!r)
2783 continue;
2784
2785 good = tpm2_pcr_mask_good(c, hash, pcr_mask);
2786 if (good < 0)
2787 return good;
2788
2789 if (hash == TPM2_ALG_SHA256) {
2790 supported_hash = TPM2_ALG_SHA256;
2791 if (good) {
2792 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2793 hash_with_valid_pcr = TPM2_ALG_SHA256;
2794 break;
2795 }
2796 } else {
2797 assert(hash == TPM2_ALG_SHA1);
2798
2799 if (supported_hash == 0)
2800 supported_hash = TPM2_ALG_SHA1;
2801
2802 if (good && hash_with_valid_pcr == 0)
2803 hash_with_valid_pcr = TPM2_ALG_SHA1;
2804 }
2805 }
2806
2807 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2808 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2809 * SHA1.
2810 *
2811 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2812 * not initialized. */
2813
2814 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
2815 assert(supported_hash == TPM2_ALG_SHA256);
2816 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2817 *ret = TPM2_ALG_SHA256;
2818 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
2819 if (supported_hash == TPM2_ALG_SHA256)
2820 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.");
2821 else {
2822 assert(supported_hash == TPM2_ALG_SHA1);
2823 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.");
2824 }
2825
2826 *ret = TPM2_ALG_SHA1;
2827 } else if (supported_hash == TPM2_ALG_SHA256) {
2828 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!");
2829 *ret = TPM2_ALG_SHA256;
2830 } else if (supported_hash == TPM2_ALG_SHA1) {
2831 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!");
2832 *ret = TPM2_ALG_SHA1;
2833 } else
2834 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2835 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2836
2837 return 0;
2838 }
2839
2840 int tpm2_get_good_pcr_banks(
2841 Tpm2Context *c,
2842 uint32_t pcr_mask,
2843 TPMI_ALG_HASH **ret) {
2844
2845 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
2846 size_t n_good_banks = 0, n_fallback_banks = 0;
2847 int r;
2848
2849 assert(c);
2850 assert(ret);
2851
2852 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2853 TPMI_ALG_HASH hash = selection->hash;
2854
2855 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2856 r = tpm2_bank_has24(selection);
2857 if (r < 0)
2858 return r;
2859 if (!r)
2860 continue;
2861
2862 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2863 r = tpm2_pcr_mask_good(c, hash, pcr_mask);
2864 if (r < 0)
2865 return r;
2866
2867 if (n_good_banks + n_fallback_banks >= INT_MAX)
2868 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
2869
2870 if (r) {
2871 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
2872 return log_oom_debug();
2873
2874 good_banks[n_good_banks++] = hash;
2875 } else {
2876 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
2877 return log_oom_debug();
2878
2879 fallback_banks[n_fallback_banks++] = hash;
2880 }
2881 }
2882
2883 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2884 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2885 if (n_good_banks > 0) {
2886 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
2887 *ret = TAKE_PTR(good_banks);
2888 return (int) n_good_banks;
2889 }
2890 if (n_fallback_banks > 0) {
2891 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
2892 *ret = TAKE_PTR(fallback_banks);
2893 return (int) n_fallback_banks;
2894 }
2895
2896 /* No suitable banks found. */
2897 *ret = NULL;
2898 return 0;
2899 }
2900
2901 int tpm2_get_good_pcr_banks_strv(
2902 Tpm2Context *c,
2903 uint32_t pcr_mask,
2904 char ***ret) {
2905
2906 #if HAVE_OPENSSL
2907 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
2908 _cleanup_strv_free_ char **l = NULL;
2909 int n_algs;
2910
2911 assert(c);
2912 assert(ret);
2913
2914 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
2915 if (n_algs < 0)
2916 return n_algs;
2917
2918 FOREACH_ARRAY(a, algs, n_algs) {
2919 _cleanup_free_ char *n = NULL;
2920 const EVP_MD *implementation;
2921 const char *salg;
2922
2923 salg = tpm2_hash_alg_to_string(*a);
2924 if (!salg)
2925 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
2926
2927 implementation = EVP_get_digestbyname(salg);
2928 if (!implementation)
2929 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2930
2931 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
2932 if (!n)
2933 return log_oom_debug();
2934
2935 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2936
2937 if (strv_consume(&l, TAKE_PTR(n)) < 0)
2938 return log_oom_debug();
2939 }
2940
2941 *ret = TAKE_PTR(l);
2942 return 0;
2943 #else /* HAVE_OPENSSL */
2944 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2945 #endif
2946 }
2947
2948 /* Hash data into the digest.
2949 *
2950 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2951 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2952 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2953 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2954 *
2955 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2956 * correct for 'alg'.
2957 *
2958 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2959 int tpm2_digest_many(
2960 TPMI_ALG_HASH alg,
2961 TPM2B_DIGEST *digest,
2962 const struct iovec data[],
2963 size_t n_data,
2964 bool extend) {
2965
2966 struct sha256_ctx ctx;
2967
2968 assert(digest);
2969 assert(data || n_data == 0);
2970
2971 if (alg != TPM2_ALG_SHA256)
2972 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2973 "Hash algorithm not supported: 0x%x", alg);
2974
2975 if (extend && digest->size != SHA256_DIGEST_SIZE)
2976 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2977 "Digest size 0x%x, require 0x%x",
2978 digest->size, (unsigned)SHA256_DIGEST_SIZE);
2979
2980 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2981 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
2982
2983 CLEANUP_ERASE(ctx);
2984
2985 sha256_init_ctx(&ctx);
2986
2987 if (extend)
2988 sha256_process_bytes(digest->buffer, digest->size, &ctx);
2989 else {
2990 *digest = (TPM2B_DIGEST) {
2991 .size = SHA256_DIGEST_SIZE,
2992 };
2993 if (n_data == 0) /* If not extending and no data, return zero hash */
2994 return 0;
2995 }
2996
2997 FOREACH_ARRAY(d, data, n_data)
2998 sha256_process_bytes(d->iov_base, d->iov_len, &ctx);
2999
3000 sha256_finish_ctx(&ctx, digest->buffer);
3001
3002 return 0;
3003 }
3004
3005 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
3006 int tpm2_digest_many_digests(
3007 TPMI_ALG_HASH alg,
3008 TPM2B_DIGEST *digest,
3009 const TPM2B_DIGEST data[],
3010 size_t n_data,
3011 bool extend) {
3012
3013 _cleanup_free_ struct iovec *iovecs = NULL;
3014
3015 assert(data || n_data == 0);
3016
3017 iovecs = new(struct iovec, n_data);
3018 if (!iovecs)
3019 return log_oom_debug();
3020
3021 for (size_t i = 0; i < n_data; i++)
3022 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
3023
3024 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
3025 }
3026
3027 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
3028 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
3029 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
3030 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
3031 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
3032 *
3033 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
3034 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
3035 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
3036 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
3037 *
3038 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
3039 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
3040 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
3041 *
3042 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
3043 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
3044 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
3045 * which we will trim the 0(s) from before sending to the TPM.
3046 */
3047 static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
3048 bool trimmed = false;
3049
3050 assert(auth);
3051
3052 while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
3053 trimmed = true;
3054 auth->size--;
3055 }
3056
3057 if (trimmed)
3058 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
3059 }
3060
3061 int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
3062 TPM2B_AUTH auth = {};
3063 int r;
3064
3065 assert(pin);
3066 assert(ret_auth);
3067
3068 r = tpm2_digest_buffer(hash, &auth, pin, strlen(pin), /* extend= */ false);
3069 if (r < 0)
3070 return r;
3071
3072 tpm2_trim_auth_value(&auth);
3073
3074 *ret_auth = TAKE_STRUCT(auth);
3075
3076 return 0;
3077 }
3078
3079 int tpm2_set_auth_binary(Tpm2Context *c, const Tpm2Handle *handle, const TPM2B_AUTH *auth) {
3080 TSS2_RC rc;
3081
3082 assert(c);
3083 assert(handle);
3084
3085 if (!auth)
3086 return 0;
3087
3088 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, auth);
3089 if (rc != TSS2_RC_SUCCESS)
3090 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3091 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
3092
3093 return 0;
3094 }
3095
3096 int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
3097 TPM2B_AUTH auth = {};
3098 int r;
3099
3100 assert(c);
3101 assert(handle);
3102
3103 if (!pin)
3104 return 0;
3105
3106 CLEANUP_ERASE(auth);
3107
3108 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &auth);
3109 if (r < 0)
3110 return r;
3111
3112 return tpm2_set_auth_binary(c, handle, &auth);
3113 }
3114
3115 static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
3116 TPMA_SESSION flags = 0;
3117 TSS2_RC rc;
3118
3119 assert(c);
3120 assert(session);
3121
3122 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
3123 if (rc != TSS2_RC_SUCCESS)
3124 return false;
3125
3126 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
3127 }
3128
3129 int tpm2_make_encryption_session(
3130 Tpm2Context *c,
3131 const Tpm2Handle *primary,
3132 const Tpm2Handle *bind_key,
3133 Tpm2Handle **ret_session) {
3134
3135 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
3136 TPMA_SESSION_CONTINUESESSION;
3137 TSS2_RC rc;
3138 int r;
3139
3140 assert(c);
3141 assert(primary);
3142 assert(ret_session);
3143
3144 log_debug("Starting HMAC encryption session.");
3145
3146 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
3147 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
3148 * recover the salt, which is then used for key derivation. */
3149 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
3150 r = tpm2_handle_new(c, &session);
3151 if (r < 0)
3152 return r;
3153
3154 rc = sym_Esys_StartAuthSession(
3155 c->esys_context,
3156 primary->esys_handle,
3157 bind_key ? bind_key->esys_handle : ESYS_TR_NONE,
3158 ESYS_TR_NONE,
3159 ESYS_TR_NONE,
3160 ESYS_TR_NONE,
3161 NULL,
3162 TPM2_SE_HMAC,
3163 &SESSION_TEMPLATE_SYM_AES_128_CFB,
3164 TPM2_ALG_SHA256,
3165 &session->esys_handle);
3166 if (rc != TSS2_RC_SUCCESS)
3167 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3168 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
3169
3170 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
3171 * always used for sessions), this provides confidentiality, integrity and replay protection for
3172 * operations that use this session. */
3173 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
3174 if (rc != TSS2_RC_SUCCESS)
3175 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3176 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc));
3177
3178 *ret_session = TAKE_PTR(session);
3179
3180 return 0;
3181 }
3182
3183 int tpm2_make_policy_session(
3184 Tpm2Context *c,
3185 const Tpm2Handle *primary,
3186 const Tpm2Handle *encryption_session,
3187 Tpm2Handle **ret_session) {
3188
3189 TSS2_RC rc;
3190 int r;
3191
3192 assert(c);
3193 assert(primary);
3194 assert(encryption_session);
3195 assert(ret_session);
3196
3197 if (!tpm2_is_encryption_session(c, encryption_session))
3198 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3199 "Missing encryption session");
3200
3201 log_debug("Starting policy session.");
3202
3203 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
3204 r = tpm2_handle_new(c, &session);
3205 if (r < 0)
3206 return r;
3207
3208 rc = sym_Esys_StartAuthSession(
3209 c->esys_context,
3210 primary->esys_handle,
3211 ESYS_TR_NONE,
3212 encryption_session->esys_handle,
3213 ESYS_TR_NONE,
3214 ESYS_TR_NONE,
3215 NULL,
3216 TPM2_SE_POLICY,
3217 &SESSION_TEMPLATE_SYM_AES_128_CFB,
3218 TPM2_ALG_SHA256,
3219 &session->esys_handle);
3220 if (rc != TSS2_RC_SUCCESS)
3221 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3222 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
3223
3224 *ret_session = TAKE_PTR(session);
3225
3226 return 0;
3227 }
3228
3229 static int find_signature(
3230 JsonVariant *v,
3231 const TPML_PCR_SELECTION *pcr_selection,
3232 const void *fp,
3233 size_t fp_size,
3234 const void *policy,
3235 size_t policy_size,
3236 void *ret_signature,
3237 size_t *ret_signature_size) {
3238
3239 #if HAVE_OPENSSL
3240 JsonVariant *b, *i;
3241 const char *k;
3242 int r;
3243
3244 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3245 * public key, and policy digest. */
3246
3247 if (!json_variant_is_object(v))
3248 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
3249
3250 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
3251 uint32_t pcr_mask = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank);
3252
3253 k = tpm2_hash_alg_to_string(pcr_bank);
3254 if (!k)
3255 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
3256
3257 /* First, find field by bank */
3258 b = json_variant_by_key(v, k);
3259 if (!b)
3260 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
3261
3262 if (!json_variant_is_array(b))
3263 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
3264
3265 /* Now iterate through all signatures known for this bank */
3266 JSON_VARIANT_ARRAY_FOREACH(i, b) {
3267 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
3268 JsonVariant *maskj, *fpj, *sigj, *polj;
3269 size_t fpj_size, polj_size;
3270 uint32_t parsed_mask;
3271
3272 if (!json_variant_is_object(i))
3273 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
3274
3275 /* Check if the PCR mask matches our expectations */
3276 maskj = json_variant_by_key(i, "pcrs");
3277 if (!maskj)
3278 continue;
3279
3280 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
3281 if (r < 0)
3282 return log_debug_errno(r, "Failed to parse JSON PCR mask");
3283
3284 if (parsed_mask != pcr_mask)
3285 continue; /* Not for this PCR mask */
3286
3287 /* Then check if this is for the public key we operate with */
3288 fpj = json_variant_by_key(i, "pkfp");
3289 if (!fpj)
3290 continue;
3291
3292 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
3293 if (r < 0)
3294 return log_debug_errno(r, "Failed to decode fingerprint in JSON data: %m");
3295
3296 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
3297 continue; /* Not for this public key */
3298
3299 /* Finally, check if this is for the PCR policy we expect this to be */
3300 polj = json_variant_by_key(i, "pol");
3301 if (!polj)
3302 continue;
3303
3304 r = json_variant_unhex(polj, &polj_data, &polj_size);
3305 if (r < 0)
3306 return log_debug_errno(r, "Failed to decode policy hash JSON data: %m");
3307
3308 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
3309 continue;
3310
3311 /* This entry matches all our expectations, now return the signature included in it */
3312 sigj = json_variant_by_key(i, "sig");
3313 if (!sigj)
3314 continue;
3315
3316 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
3317 }
3318
3319 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
3320 #else /* HAVE_OPENSSL */
3321 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3322 #endif
3323 }
3324
3325 /* Calculates the "name" of a public key.
3326 *
3327 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3328 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3329 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3330 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3331 * that would also change the key name.
3332 *
3333 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3334 * nameAlg is not TPM2_ALG_SHA256. */
3335 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
3336 TSS2_RC rc;
3337 int r;
3338
3339 assert(public);
3340 assert(ret_name);
3341
3342 r = dlopen_tpm2();
3343 if (r < 0)
3344 return log_debug_errno(r, "TPM2 support not installed: %m");
3345
3346 if (public->nameAlg != TPM2_ALG_SHA256)
3347 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3348 "Unsupported nameAlg: 0x%x",
3349 public->nameAlg);
3350
3351 _cleanup_free_ uint8_t *buf = NULL;
3352 size_t size = 0;
3353
3354 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
3355 if (!buf)
3356 return log_oom_debug();
3357
3358 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
3359 if (rc != TSS2_RC_SUCCESS)
3360 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3361 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
3362
3363 TPM2B_DIGEST digest = {};
3364 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3365 if (r < 0)
3366 return r;
3367
3368 TPMT_HA ha = {
3369 .hashAlg = TPM2_ALG_SHA256,
3370 };
3371 assert(digest.size <= sizeof(ha.digest.sha256));
3372 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3373
3374 TPM2B_NAME name;
3375 size = 0;
3376 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3377 if (rc != TSS2_RC_SUCCESS)
3378 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3379 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
3380 name.size = size;
3381
3382 tpm2_log_debug_name(&name, "Calculated public key name");
3383
3384 *ret_name = name;
3385
3386 return 0;
3387 }
3388
3389 /* Get the "name" of a key from the TPM.
3390 *
3391 * The "name" of a key is explained above in tpm2_calculate_pubkey_name().
3392 *
3393 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3394 * public/private keypair. */
3395 static int tpm2_get_name(
3396 Tpm2Context *c,
3397 const Tpm2Handle *handle,
3398 TPM2B_NAME **ret_name) {
3399
3400 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
3401 TSS2_RC rc;
3402
3403 assert(c);
3404 assert(handle);
3405 assert(ret_name);
3406
3407 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
3408 if (rc != TSS2_RC_SUCCESS)
3409 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3410 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
3411
3412 tpm2_log_debug_name(name, "Object name");
3413
3414 *ret_name = TAKE_PTR(name);
3415
3416 return 0;
3417 }
3418
3419 int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC *nvpublic, TPM2B_NAME *ret_name) {
3420 TSS2_RC rc;
3421 int r;
3422
3423 assert(nvpublic);
3424 assert(ret_name);
3425
3426 r = dlopen_tpm2();
3427 if (r < 0)
3428 return log_debug_errno(r, "TPM2 support not installed: %m");
3429
3430 if (nvpublic->nameAlg != TPM2_ALG_SHA256)
3431 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3432 "Unsupported nameAlg: 0x%x",
3433 nvpublic->nameAlg);
3434
3435 _cleanup_free_ uint8_t *buf = NULL;
3436 size_t size = 0;
3437
3438 buf = (uint8_t*) new(TPMS_NV_PUBLIC, 1);
3439 if (!buf)
3440 return log_oom_debug();
3441
3442 rc = sym_Tss2_MU_TPMS_NV_PUBLIC_Marshal(nvpublic, buf, sizeof(TPMS_NV_PUBLIC), &size);
3443 if (rc != TSS2_RC_SUCCESS)
3444 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3445 "Failed to marshal NV index: %s", sym_Tss2_RC_Decode(rc));
3446
3447 TPM2B_DIGEST digest = {};
3448 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3449 if (r < 0)
3450 return r;
3451
3452 TPMT_HA ha = {
3453 .hashAlg = TPM2_ALG_SHA256,
3454 };
3455 assert(digest.size <= sizeof(ha.digest.sha256));
3456 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3457
3458 TPM2B_NAME name;
3459 size = 0;
3460 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3461 if (rc != TSS2_RC_SUCCESS)
3462 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3463 "Failed to marshal NV index name: %s", sym_Tss2_RC_Decode(rc));
3464 name.size = size;
3465
3466 tpm2_log_debug_name(&name, "Calculated NV index name");
3467
3468 *ret_name = name;
3469
3470 return 0;
3471 }
3472
3473 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3474 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
3475 TPM2_CC command = TPM2_CC_PolicyAuthValue;
3476 TSS2_RC rc;
3477 int r;
3478
3479 assert(digest);
3480 assert(digest->size == SHA256_DIGEST_SIZE);
3481
3482 r = dlopen_tpm2();
3483 if (r < 0)
3484 return log_debug_errno(r, "TPM2 support not installed: %m");
3485
3486 uint8_t buf[sizeof(command)];
3487 size_t offset = 0;
3488
3489 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3490 if (rc != TSS2_RC_SUCCESS)
3491 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3492 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
3493
3494 if (offset != sizeof(command))
3495 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3496 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
3497
3498 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
3499 if (r < 0)
3500 return r;
3501
3502 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
3503
3504 return 0;
3505 }
3506
3507 int tpm2_policy_auth_value(
3508 Tpm2Context *c,
3509 const Tpm2Handle *session,
3510 TPM2B_DIGEST **ret_policy_digest) {
3511
3512 TSS2_RC rc;
3513
3514 assert(c);
3515 assert(session);
3516
3517 log_debug("Submitting AuthValue policy.");
3518
3519 rc = sym_Esys_PolicyAuthValue(
3520 c->esys_context,
3521 session->esys_handle,
3522 ESYS_TR_NONE,
3523 ESYS_TR_NONE,
3524 ESYS_TR_NONE);
3525 if (rc != TSS2_RC_SUCCESS)
3526 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3527 "Failed to add authValue policy to TPM: %s",
3528 sym_Tss2_RC_Decode(rc));
3529
3530 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3531 }
3532
3533 int tpm2_calculate_policy_authorize_nv(
3534 const TPM2B_NV_PUBLIC *public_info,
3535 TPM2B_DIGEST *digest) {
3536 TPM2_CC command = TPM2_CC_PolicyAuthorizeNV;
3537 TSS2_RC rc;
3538 int r;
3539
3540 assert(public_info);
3541 assert(digest);
3542 assert(digest->size == SHA256_DIGEST_SIZE);
3543
3544 r = dlopen_tpm2();
3545 if (r < 0)
3546 return log_debug_errno(r, "TPM2 support not installed: %m");
3547
3548 uint8_t buf[sizeof(command)];
3549 size_t offset = 0;
3550
3551 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3552 if (rc != TSS2_RC_SUCCESS)
3553 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3554 "Failed to marshal PolicyAuthorizeNV command: %s", sym_Tss2_RC_Decode(rc));
3555
3556 if (offset != sizeof(command))
3557 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3558 "Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset);
3559
3560 TPM2B_NV_PUBLIC public_info_copy = *public_info; /* Make a copy, since we must set TPMA_NV_WRITTEN for the calculation */
3561 public_info_copy.nvPublic.attributes |= TPMA_NV_WRITTEN;
3562
3563 TPM2B_NAME name = {};
3564 r = tpm2_calculate_nv_index_name(&public_info_copy.nvPublic, &name);
3565 if (r < 0)
3566 return r;
3567
3568 struct iovec data[] = {
3569 IOVEC_MAKE(buf, offset),
3570 IOVEC_MAKE(name.name, name.size),
3571 };
3572
3573 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3574 if (r < 0)
3575 return r;
3576
3577 tpm2_log_debug_digest(digest, "PolicyAuthorizeNV calculated digest");
3578
3579 return 0;
3580 }
3581
3582 int tpm2_policy_authorize_nv(
3583 Tpm2Context *c,
3584 const Tpm2Handle *session,
3585 const Tpm2Handle *nv_handle,
3586 TPM2B_DIGEST **ret_policy_digest) {
3587
3588 TSS2_RC rc;
3589
3590 assert(c);
3591 assert(session);
3592
3593 log_debug("Submitting AuthorizeNV policy.");
3594
3595 rc = sym_Esys_PolicyAuthorizeNV(
3596 c->esys_context,
3597 ESYS_TR_RH_OWNER,
3598 nv_handle->esys_handle,
3599 session->esys_handle,
3600 ESYS_TR_PASSWORD,
3601 ESYS_TR_NONE,
3602 ESYS_TR_NONE);
3603 if (rc != TSS2_RC_SUCCESS)
3604 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3605 "Failed to add AuthorizeNV policy to TPM: %s",
3606 sym_Tss2_RC_Decode(rc));
3607
3608 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3609 }
3610
3611 int tpm2_policy_or(
3612 Tpm2Context *c,
3613 const Tpm2Handle *session,
3614 const TPM2B_DIGEST *branches, size_t n_branches,
3615 TPM2B_DIGEST **ret_policy_digest) {
3616
3617 TPML_DIGEST hash_list;
3618 TSS2_RC rc;
3619
3620 assert(c);
3621 assert(session);
3622
3623 if (n_branches > ELEMENTSOF(hash_list.digests))
3624 return -EOPNOTSUPP;
3625
3626 log_debug("Submitting OR policy.");
3627
3628 hash_list = (TPML_DIGEST) {
3629 .count = n_branches,
3630 };
3631
3632 memcpy(hash_list.digests, branches, n_branches * sizeof(TPM2B_DIGEST));
3633
3634 if (DEBUG_LOGGING)
3635 for (size_t i = 0; i < hash_list.count; i++) {
3636 _cleanup_free_ char *h = hexmem(hash_list.digests[i].buffer, hash_list.digests[i].size);
3637 log_debug("Submitting OR Branch #%zu: %s", i, h);
3638 }
3639
3640 rc = sym_Esys_PolicyOR(
3641 c->esys_context,
3642 session->esys_handle,
3643 ESYS_TR_NONE,
3644 ESYS_TR_NONE,
3645 ESYS_TR_NONE,
3646 &hash_list);
3647 if (rc != TSS2_RC_SUCCESS)
3648 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3649 "Failed to add OR policy to TPM: %s",
3650 sym_Tss2_RC_Decode(rc));
3651
3652 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3653 }
3654
3655 /* Extend 'digest' with the PolicyOR calculated hash. */
3656 int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TPM2B_DIGEST *digest) {
3657 TPM2_CC command = TPM2_CC_PolicyOR;
3658 TSS2_RC rc;
3659 int r;
3660
3661 assert(digest);
3662 assert(digest->size == SHA256_DIGEST_SIZE);
3663
3664 if (n_branches == 0)
3665 return -EINVAL;
3666 if (n_branches == 1)
3667 log_warning("PolicyOR with a single branch submitted, this is weird.");
3668 if (n_branches > 8)
3669 return -E2BIG;
3670
3671 r = dlopen_tpm2();
3672 if (r < 0)
3673 return log_error_errno(r, "TPM2 support not installed: %m");
3674
3675 uint8_t buf[sizeof(command)];
3676 size_t offset = 0;
3677
3678 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3679 if (rc != TSS2_RC_SUCCESS)
3680 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3681 "Failed to marshal PolicyOR command: %s", sym_Tss2_RC_Decode(rc));
3682
3683 if (offset != sizeof(command))
3684 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3685 "Offset 0x%zx wrong after marshalling PolicyOR command", offset);
3686 _cleanup_free_ struct iovec *data = new(struct iovec, 1 + n_branches);
3687 if (!data)
3688 return log_oom();
3689
3690 data[0] = IOVEC_MAKE(buf, offset);
3691 for (size_t i = 0; i < n_branches; i++) {
3692 data[1 + i] = IOVEC_MAKE((void*) branches[i].buffer, branches[i].size);
3693
3694 if (DEBUG_LOGGING) {
3695 _cleanup_free_ char *h = hexmem(branches[i].buffer, branches[i].size);
3696 log_debug("OR Branch #%zu: %s", i, h);
3697 }
3698 }
3699
3700 /* PolicyOR does not use the previous hash value; we must zero and then extend it. */
3701 zero(digest->buffer);
3702
3703 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, 1 + n_branches, /* extend= */ true);
3704 if (r < 0)
3705 return r;
3706
3707 tpm2_log_debug_digest(digest, "PolicyOR calculated digest");
3708
3709 return 0;
3710 }
3711
3712 /* Extend 'digest' with the PolicyPCR calculated hash. */
3713 int tpm2_calculate_policy_pcr(
3714 const Tpm2PCRValue *pcr_values,
3715 size_t n_pcr_values,
3716 TPM2B_DIGEST *digest) {
3717
3718 TPM2_CC command = TPM2_CC_PolicyPCR;
3719 TSS2_RC rc;
3720 int r;
3721
3722 assert(pcr_values || n_pcr_values == 0);
3723 assert(digest);
3724 assert(digest->size == SHA256_DIGEST_SIZE);
3725
3726 r = dlopen_tpm2();
3727 if (r < 0)
3728 return log_debug_errno(r, "TPM2 support not installed: %m");
3729
3730 TPML_PCR_SELECTION pcr_selection;
3731 _cleanup_free_ TPM2B_DIGEST *values = NULL;
3732 size_t n_values;
3733 r = tpm2_tpml_pcr_selection_from_pcr_values(pcr_values, n_pcr_values, &pcr_selection, &values, &n_values);
3734 if (r < 0)
3735 return log_debug_errno(r, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3736
3737 TPM2B_DIGEST hash = {};
3738 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, values, n_values, /* extend= */ false);
3739 if (r < 0)
3740 return r;
3741
3742 _cleanup_free_ uint8_t *buf = NULL;
3743 size_t size = 0, maxsize = sizeof(command) + sizeof(pcr_selection);
3744
3745 buf = malloc(maxsize);
3746 if (!buf)
3747 return log_oom_debug();
3748
3749 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
3750 if (rc != TSS2_RC_SUCCESS)
3751 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3752 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
3753
3754 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection, buf, maxsize, &size);
3755 if (rc != TSS2_RC_SUCCESS)
3756 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3757 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
3758
3759 struct iovec data[] = {
3760 IOVEC_MAKE(buf, size),
3761 IOVEC_MAKE(hash.buffer, hash.size),
3762 };
3763 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3764 if (r < 0)
3765 return r;
3766
3767 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
3768
3769 return 0;
3770 }
3771
3772 int tpm2_policy_pcr(
3773 Tpm2Context *c,
3774 const Tpm2Handle *session,
3775 const TPML_PCR_SELECTION *pcr_selection,
3776 TPM2B_DIGEST **ret_policy_digest) {
3777
3778 TSS2_RC rc;
3779
3780 assert(c);
3781 assert(session);
3782 assert(pcr_selection);
3783
3784 log_debug("Submitting PCR hash policy.");
3785
3786 rc = sym_Esys_PolicyPCR(
3787 c->esys_context,
3788 session->esys_handle,
3789 ESYS_TR_NONE,
3790 ESYS_TR_NONE,
3791 ESYS_TR_NONE,
3792 NULL,
3793 pcr_selection);
3794 if (rc != TSS2_RC_SUCCESS)
3795 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3796 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
3797
3798 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3799 }
3800
3801 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3802 int tpm2_calculate_policy_authorize(
3803 const TPM2B_PUBLIC *public,
3804 const TPM2B_DIGEST *policy_ref,
3805 TPM2B_DIGEST *digest) {
3806
3807 TPM2_CC command = TPM2_CC_PolicyAuthorize;
3808 TSS2_RC rc;
3809 int r;
3810
3811 assert(public);
3812 assert(digest);
3813 assert(digest->size == SHA256_DIGEST_SIZE);
3814
3815 r = dlopen_tpm2();
3816 if (r < 0)
3817 return log_debug_errno(r, "TPM2 support not installed: %m");
3818
3819 uint8_t buf[sizeof(command)];
3820 size_t offset = 0;
3821
3822 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3823 if (rc != TSS2_RC_SUCCESS)
3824 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3825 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
3826
3827 if (offset != sizeof(command))
3828 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3829 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
3830
3831 TPM2B_NAME name = {};
3832 r = tpm2_calculate_pubkey_name(&public->publicArea, &name);
3833 if (r < 0)
3834 return r;
3835
3836 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3837 zero(digest->buffer);
3838
3839 struct iovec data[] = {
3840 IOVEC_MAKE(buf, offset),
3841 IOVEC_MAKE(name.name, name.size),
3842 };
3843 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3844 if (r < 0)
3845 return r;
3846
3847 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3848 if (policy_ref)
3849 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
3850 else
3851 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
3852 if (r < 0)
3853 return r;
3854
3855 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
3856
3857 return 0;
3858 }
3859
3860 static int tpm2_policy_authorize(
3861 Tpm2Context *c,
3862 const Tpm2Handle *session,
3863 TPML_PCR_SELECTION *pcr_selection,
3864 const TPM2B_PUBLIC *public,
3865 const void *fp,
3866 size_t fp_size,
3867 JsonVariant *signature_json,
3868 TPM2B_DIGEST **ret_policy_digest) {
3869
3870 TSS2_RC rc;
3871 int r;
3872
3873 assert(c);
3874 assert(session);
3875 assert(pcr_selection);
3876 assert(public);
3877 assert(fp && fp_size > 0);
3878
3879 log_debug("Adding PCR signature policy.");
3880
3881 _cleanup_(tpm2_handle_freep) Tpm2Handle *pubkey_handle = NULL;
3882 r = tpm2_load_external(c, NULL, public, NULL, &pubkey_handle);
3883 if (r < 0)
3884 return r;
3885
3886 /* Acquire the "name" of what we just loaded */
3887 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
3888 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
3889 if (r < 0)
3890 return r;
3891
3892 /* If we have a signature, proceed with verifying the PCR digest */
3893 const TPMT_TK_VERIFIED *check_ticket;
3894 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
3895 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
3896 if (signature_json) {
3897 r = tpm2_policy_pcr(
3898 c,
3899 session,
3900 pcr_selection,
3901 &approved_policy);
3902 if (r < 0)
3903 return r;
3904
3905 _cleanup_free_ void *signature_raw = NULL;
3906 size_t signature_size;
3907
3908 r = find_signature(
3909 signature_json,
3910 pcr_selection,
3911 fp, fp_size,
3912 approved_policy->buffer,
3913 approved_policy->size,
3914 &signature_raw,
3915 &signature_size);
3916 if (r < 0)
3917 return r;
3918
3919 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3920 * hence we need to do the SHA256 part ourselves, first */
3921 TPM2B_DIGEST signature_hash = *approved_policy;
3922 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
3923 if (r < 0)
3924 return r;
3925
3926 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size);
3927 if (r < 0)
3928 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
3929
3930 TPMT_SIGNATURE policy_signature = {
3931 .sigAlg = TPM2_ALG_RSASSA,
3932 .signature.rsassa = {
3933 .hash = TPM2_ALG_SHA256,
3934 .sig = TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw, signature_size),
3935 },
3936 };
3937
3938 rc = sym_Esys_VerifySignature(
3939 c->esys_context,
3940 pubkey_handle->esys_handle,
3941 ESYS_TR_NONE,
3942 ESYS_TR_NONE,
3943 ESYS_TR_NONE,
3944 &signature_hash,
3945 &policy_signature,
3946 &check_ticket_buffer);
3947 if (rc != TSS2_RC_SUCCESS)
3948 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3949 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
3950
3951 check_ticket = check_ticket_buffer;
3952 } else {
3953 /* When enrolling, we pass a NULL ticket */
3954 static const TPMT_TK_VERIFIED check_ticket_null = {
3955 .tag = TPM2_ST_VERIFIED,
3956 .hierarchy = TPM2_RH_OWNER,
3957 };
3958
3959 check_ticket = &check_ticket_null;
3960 }
3961
3962 rc = sym_Esys_PolicyAuthorize(
3963 c->esys_context,
3964 session->esys_handle,
3965 ESYS_TR_NONE,
3966 ESYS_TR_NONE,
3967 ESYS_TR_NONE,
3968 approved_policy,
3969 /* policyRef= */ &(const TPM2B_NONCE) {},
3970 pubkey_name,
3971 check_ticket);
3972 if (rc != TSS2_RC_SUCCESS)
3973 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3974 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
3975
3976 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3977 }
3978
3979 /* Extend 'digest' with the calculated policy hash. */
3980 int tpm2_calculate_sealing_policy(
3981 const Tpm2PCRValue *pcr_values,
3982 size_t n_pcr_values,
3983 const TPM2B_PUBLIC *public,
3984 bool use_pin,
3985 const Tpm2PCRLockPolicy *pcrlock_policy,
3986 TPM2B_DIGEST *digest) {
3987
3988 int r;
3989
3990 assert(pcr_values || n_pcr_values == 0);
3991 assert(digest);
3992
3993 if (public && pcrlock_policy)
3994 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Policies with both signed PCR and pcrlock are currently not supported.");
3995
3996 if (public) {
3997 r = tpm2_calculate_policy_authorize(public, NULL, digest);
3998 if (r < 0)
3999 return r;
4000 }
4001
4002 if (pcrlock_policy) {
4003 TPM2B_NV_PUBLIC nv_public;
4004
4005 r = tpm2_unmarshal_nv_public(
4006 pcrlock_policy->nv_public.iov_base,
4007 pcrlock_policy->nv_public.iov_len,
4008 &nv_public);
4009 if (r < 0)
4010 return r;
4011
4012 r = tpm2_calculate_policy_authorize_nv(&nv_public, digest);
4013 if (r < 0)
4014 return r;
4015 }
4016
4017 if (n_pcr_values > 0) {
4018 r = tpm2_calculate_policy_pcr(pcr_values, n_pcr_values, digest);
4019 if (r < 0)
4020 return r;
4021 }
4022
4023 if (use_pin) {
4024 r = tpm2_calculate_policy_auth_value(digest);
4025 if (r < 0)
4026 return r;
4027 }
4028
4029 return 0;
4030 }
4031
4032 static int tpm2_build_sealing_policy(
4033 Tpm2Context *c,
4034 const Tpm2Handle *session,
4035 uint32_t hash_pcr_mask,
4036 uint16_t pcr_bank,
4037 const TPM2B_PUBLIC *public,
4038 const void *fp,
4039 size_t fp_size,
4040 uint32_t pubkey_pcr_mask,
4041 JsonVariant *signature_json,
4042 bool use_pin,
4043 const Tpm2PCRLockPolicy *pcrlock_policy,
4044 TPM2B_DIGEST **ret_policy_digest) {
4045
4046 int r;
4047
4048 assert(c);
4049 assert(session);
4050 assert(pubkey_pcr_mask == 0 || public);
4051
4052 log_debug("Building sealing policy.");
4053
4054 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
4055 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
4056 if (r < 0)
4057 return r;
4058 if (r == 0)
4059 log_debug("Selected TPM2 PCRs are not initialized on this system.");
4060 }
4061
4062 if (pubkey_pcr_mask != 0 && pcrlock_policy)
4063 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Policies with both signed PCR and pcrlock are currently not supported.");
4064
4065 if (pubkey_pcr_mask != 0) {
4066 TPML_PCR_SELECTION pcr_selection;
4067 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
4068 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
4069 if (r < 0)
4070 return r;
4071 }
4072
4073 if (pcrlock_policy) {
4074 _cleanup_(tpm2_handle_freep) Tpm2Handle *nv_handle = NULL;
4075
4076 r = tpm2_policy_super_pcr(
4077 c,
4078 session,
4079 &pcrlock_policy->prediction,
4080 pcrlock_policy->algorithm);
4081 if (r < 0)
4082 return r;
4083
4084 r = tpm2_deserialize(
4085 c,
4086 pcrlock_policy->nv_handle.iov_base,
4087 pcrlock_policy->nv_handle.iov_len,
4088 &nv_handle);
4089 if (r < 0)
4090 return r;
4091
4092 r = tpm2_policy_authorize_nv(
4093 c,
4094 session,
4095 nv_handle,
4096 NULL);
4097 if (r < 0)
4098 return r;
4099 }
4100
4101 if (hash_pcr_mask != 0) {
4102 TPML_PCR_SELECTION pcr_selection;
4103 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
4104 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
4105 if (r < 0)
4106 return r;
4107 }
4108
4109 if (use_pin) {
4110 r = tpm2_policy_auth_value(c, session, NULL);
4111 if (r < 0)
4112 return r;
4113 }
4114
4115 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
4116 if (r < 0)
4117 return r;
4118
4119 return 0;
4120 }
4121
4122 #if HAVE_OPENSSL
4123 static const struct {
4124 TPM2_ECC_CURVE tpm2_ecc_curve_id;
4125 int openssl_ecc_curve_id;
4126 } tpm2_openssl_ecc_curve_table[] = {
4127 { TPM2_ECC_NIST_P192, NID_X9_62_prime192v1, },
4128 { TPM2_ECC_NIST_P224, NID_secp224r1, },
4129 { TPM2_ECC_NIST_P256, NID_X9_62_prime256v1, },
4130 { TPM2_ECC_NIST_P384, NID_secp384r1, },
4131 { TPM2_ECC_NIST_P521, NID_secp521r1, },
4132 { TPM2_ECC_SM2_P256, NID_sm2, },
4133 };
4134
4135 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id, TPM2_ECC_CURVE *ret) {
4136 assert(ret);
4137
4138 FOREACH_ELEMENT(t, tpm2_openssl_ecc_curve_table)
4139 if (t->openssl_ecc_curve_id == openssl_ecc_curve_id) {
4140 *ret = t->tpm2_ecc_curve_id;
4141 return 0;
4142 }
4143
4144 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4145 "OpenSSL ECC curve id %d not supported.", openssl_ecc_curve_id);
4146 }
4147
4148 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id, int *ret) {
4149 assert(ret);
4150
4151 FOREACH_ELEMENT(t, tpm2_openssl_ecc_curve_table)
4152 if (t->tpm2_ecc_curve_id == tpm2_ecc_curve_id) {
4153 *ret = t->openssl_ecc_curve_id;
4154 return 0;
4155 }
4156
4157 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4158 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id);
4159 }
4160
4161 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
4162
4163 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret) {
4164 int r;
4165
4166 assert(public);
4167 assert(ret);
4168
4169 const TPMT_PUBLIC *p = &public->publicArea;
4170 switch (p->type) {
4171 case TPM2_ALG_ECC: {
4172 int curve_id;
4173 r = tpm2_ecc_curve_to_openssl_curve_id(p->parameters.eccDetail.curveID, &curve_id);
4174 if (r < 0)
4175 return r;
4176
4177 const TPMS_ECC_POINT *point = &p->unique.ecc;
4178 return ecc_pkey_from_curve_x_y(
4179 curve_id,
4180 point->x.buffer,
4181 point->x.size,
4182 point->y.buffer,
4183 point->y.size,
4184 ret);
4185 }
4186 case TPM2_ALG_RSA: {
4187 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4188 * zero indicates that the exponent is the default of 2^16 + 1". */
4189 uint32_t exponent = htobe32(p->parameters.rsaDetail.exponent ?: TPM2_RSA_DEFAULT_EXPONENT);
4190 return rsa_pkey_from_n_e(
4191 p->unique.rsa.buffer,
4192 p->unique.rsa.size,
4193 &exponent,
4194 sizeof(exponent),
4195 ret);
4196 }
4197 default:
4198 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4199 "TPM2 asymmetric algorithm 0x%" PRIx16 " not supported.", p->type);
4200 }
4201 }
4202
4203 /* Be careful before changing anything in this function, as the TPM key "name" is calculated using the entire
4204 * TPMT_PUBLIC (after marshalling), and that "name" is used (for example) to calculate the policy hash for
4205 * the Authorize policy. So we must ensure this conversion of a PEM to TPM2B_PUBLIC does not change the
4206 * "name", because it would break unsealing of previously-sealed objects that used (for example)
4207 * tpm2_calculate_policy_authorize(). See bug #30546. */
4208 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) {
4209 int key_id, r;
4210
4211 assert(pkey);
4212 assert(ret);
4213
4214 TPMT_PUBLIC public = {
4215 .nameAlg = TPM2_ALG_SHA256,
4216 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
4217 .parameters.asymDetail = {
4218 .symmetric.algorithm = TPM2_ALG_NULL,
4219 .scheme.scheme = TPM2_ALG_NULL,
4220 },
4221 };
4222
4223 #if OPENSSL_VERSION_MAJOR >= 3
4224 key_id = EVP_PKEY_get_id(pkey);
4225 #else
4226 key_id = EVP_PKEY_id(pkey);
4227 #endif
4228
4229 switch (key_id) {
4230 case EVP_PKEY_EC: {
4231 public.type = TPM2_ALG_ECC;
4232
4233 int curve_id;
4234 _cleanup_free_ void *x = NULL, *y = NULL;
4235 size_t x_size, y_size;
4236 r = ecc_pkey_to_curve_x_y(pkey, &curve_id, &x, &x_size, &y, &y_size);
4237 if (r < 0)
4238 return log_debug_errno(r, "Could not get ECC key curve/x/y: %m");
4239
4240 TPM2_ECC_CURVE curve;
4241 r = tpm2_ecc_curve_from_openssl_curve_id(curve_id, &curve);
4242 if (r < 0)
4243 return r;
4244
4245 public.parameters.eccDetail.curveID = curve;
4246
4247 public.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
4248
4249 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
4250 if (r < 0)
4251 return log_debug_errno(r, "ECC key x size %zu too large.", x_size);
4252
4253 public.unique.ecc.x = TPM2B_ECC_PARAMETER_MAKE(x, x_size);
4254
4255 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
4256 if (r < 0)
4257 return log_debug_errno(r, "ECC key y size %zu too large.", y_size);
4258
4259 public.unique.ecc.y = TPM2B_ECC_PARAMETER_MAKE(y, y_size);
4260
4261 break;
4262 }
4263 case EVP_PKEY_RSA: {
4264 public.type = TPM2_ALG_RSA;
4265
4266 _cleanup_free_ void *n = NULL, *e = NULL;
4267 size_t n_size, e_size;
4268 r = rsa_pkey_to_n_e(pkey, &n, &n_size, &e, &e_size);
4269 if (r < 0)
4270 return log_debug_errno(r, "Could not get RSA key n/e: %m");
4271
4272 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size);
4273 if (r < 0)
4274 return log_debug_errno(r, "RSA key n size %zu too large.", n_size);
4275
4276 public.unique.rsa = TPM2B_PUBLIC_KEY_RSA_MAKE(n, n_size);
4277 public.parameters.rsaDetail.keyBits = n_size * 8;
4278
4279 if (sizeof(uint32_t) < e_size)
4280 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
4281 "RSA key e size %zu too large.", e_size);
4282
4283 uint32_t exponent = 0;
4284 memcpy(&exponent, e, e_size);
4285 exponent = be32toh(exponent) >> (32 - e_size * 8);
4286
4287 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4288 * zero indicates that the exponent is the default of 2^16 + 1". However, we have no reason
4289 * to special case it in our PEM->TPM2B_PUBLIC conversion, and doing so could break backwards
4290 * compatibility, so even if it is the "default" value of 0x10001, we do not set it to 0. */
4291 public.parameters.rsaDetail.exponent = exponent;
4292
4293 break;
4294 }
4295 default:
4296 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4297 "EVP_PKEY type %d not supported.", key_id);
4298 }
4299
4300 *ret = (TPM2B_PUBLIC) {
4301 .size = sizeof(public),
4302 .publicArea = public,
4303 };
4304
4305 return 0;
4306 }
4307 #endif
4308
4309 int tpm2_tpm2b_public_to_fingerprint(
4310 const TPM2B_PUBLIC *public,
4311 void **ret_fingerprint,
4312 size_t *ret_fingerprint_size) {
4313
4314 #if HAVE_OPENSSL
4315 int r;
4316
4317 assert(public);
4318 assert(ret_fingerprint);
4319 assert(ret_fingerprint_size);
4320
4321 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4322 r = tpm2_tpm2b_public_to_openssl_pkey(public, &pkey);
4323 if (r < 0)
4324 return r;
4325
4326 /* Hardcode fingerprint to SHA256 */
4327 return pubkey_fingerprint(pkey, EVP_sha256(), ret_fingerprint, ret_fingerprint_size);
4328 #else
4329 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
4330 #endif
4331 }
4332
4333 int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) {
4334 #if HAVE_OPENSSL
4335 int r;
4336
4337 assert(pem);
4338 assert(ret);
4339
4340 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4341 r = openssl_pkey_from_pem(pem, pem_size, &pkey);
4342 if (r < 0)
4343 return r;
4344
4345 return tpm2_tpm2b_public_from_openssl_pkey(pkey, ret);
4346 #else
4347 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
4348 #endif
4349 }
4350
4351 /* Marshal the public, private, and seed objects into a single nonstandard 'blob'. The public and private
4352 * objects are required, while the seed is optional. This is not a (publicly) standard format, this is
4353 * specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
4354 * tpm2_unmarshal_blob(). */
4355 int tpm2_marshal_blob(
4356 const TPM2B_PUBLIC *public,
4357 const TPM2B_PRIVATE *private,
4358 const TPM2B_ENCRYPTED_SECRET *seed,
4359 void **ret_blob,
4360 size_t *ret_blob_size) {
4361
4362 TSS2_RC rc;
4363
4364 assert(public);
4365 assert(private);
4366 assert(ret_blob);
4367 assert(ret_blob_size);
4368
4369 size_t max_size = sizeof(*private) + sizeof(*public);
4370 if (seed)
4371 max_size += sizeof(*seed);
4372
4373 _cleanup_free_ void *blob = malloc(max_size);
4374 if (!blob)
4375 return log_oom_debug();
4376
4377 size_t blob_size = 0;
4378 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
4379 if (rc != TSS2_RC_SUCCESS)
4380 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4381 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
4382
4383 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
4384 if (rc != TSS2_RC_SUCCESS)
4385 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4386 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
4387
4388 if (seed) {
4389 rc = sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal(seed, blob, max_size, &blob_size);
4390 if (rc != TSS2_RC_SUCCESS)
4391 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4392 "Failed to marshal encrypted seed: %s", sym_Tss2_RC_Decode(rc));
4393 }
4394
4395 *ret_blob = TAKE_PTR(blob);
4396 *ret_blob_size = blob_size;
4397
4398 return 0;
4399 }
4400
4401 /* Unmarshal the 'blob' into public, private, and seed objects. The public and private objects are required
4402 * in the 'blob', while the seed is optional. This is not a (publicly) standard format, this is specific to
4403 * how we currently store the sealed object. This expects the 'blob' to have been created by
4404 * tpm2_marshal_blob(). */
4405 int tpm2_unmarshal_blob(
4406 const void *blob,
4407 size_t blob_size,
4408 TPM2B_PUBLIC *ret_public,
4409 TPM2B_PRIVATE *ret_private,
4410 TPM2B_ENCRYPTED_SECRET *ret_seed) {
4411
4412 TSS2_RC rc;
4413
4414 assert(blob);
4415 assert(ret_public);
4416 assert(ret_private);
4417 assert(ret_seed);
4418
4419 TPM2B_PRIVATE private = {};
4420 size_t offset = 0;
4421 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
4422 if (rc != TSS2_RC_SUCCESS)
4423 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4424 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
4425
4426 TPM2B_PUBLIC public = {};
4427 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
4428 if (rc != TSS2_RC_SUCCESS)
4429 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4430 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
4431
4432 TPM2B_ENCRYPTED_SECRET seed = {};
4433 if (blob_size > offset) {
4434 rc = sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal(blob, blob_size, &offset, &seed);
4435 if (rc != TSS2_RC_SUCCESS)
4436 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4437 "Failed to unmarshal encrypted seed: %s", sym_Tss2_RC_Decode(rc));
4438 }
4439
4440 *ret_public = public;
4441 *ret_private = private;
4442 *ret_seed = seed;
4443
4444 return 0;
4445 }
4446
4447 /* Calculate a serialized handle. Once the upstream tpm2-tss library provides an api to do this, we can
4448 * remove this function. The addition of this functionality in tpm2-tss may be tracked here:
4449 * https://github.com/tpm2-software/tpm2-tss/issues/2575 */
4450 int tpm2_calculate_serialize(
4451 TPM2_HANDLE handle,
4452 const TPM2B_NAME *name,
4453 const TPM2B_PUBLIC *public,
4454 void **ret_serialized,
4455 size_t *ret_serialized_size) {
4456
4457 TSS2_RC rc;
4458
4459 assert(name);
4460 assert(public);
4461 assert(ret_serialized);
4462 assert(ret_serialized_size);
4463
4464 size_t max_size = sizeof(TPM2_HANDLE) + sizeof(TPM2B_NAME) + sizeof(uint32_t) + sizeof(TPM2B_PUBLIC);
4465 _cleanup_free_ void *serialized = malloc(max_size);
4466 if (!serialized)
4467 return log_oom_debug();
4468
4469 size_t serialized_size = 0;
4470 rc = sym_Tss2_MU_TPM2_HANDLE_Marshal(handle, serialized, max_size, &serialized_size);
4471 if (rc != TSS2_RC_SUCCESS)
4472 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4473 "Failed to marshal tpm handle: %s", sym_Tss2_RC_Decode(rc));
4474
4475 rc = sym_Tss2_MU_TPM2B_NAME_Marshal(name, serialized, max_size, &serialized_size);
4476 if (rc != TSS2_RC_SUCCESS)
4477 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4478 "Failed to marshal name: %s", sym_Tss2_RC_Decode(rc));
4479
4480 /* This is defined (non-publicly) in the tpm2-tss source as IESYSC_KEY_RSRC, to a value of "1". */
4481 rc = sym_Tss2_MU_UINT32_Marshal(UINT32_C(1), serialized, max_size, &serialized_size);
4482 if (rc != TSS2_RC_SUCCESS)
4483 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4484 "Failed to marshal esys resource id: %s", sym_Tss2_RC_Decode(rc));
4485
4486 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, serialized, max_size, &serialized_size);
4487 if (rc != TSS2_RC_SUCCESS)
4488 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4489 "Failed to marshal public: %s", sym_Tss2_RC_Decode(rc));
4490
4491 *ret_serialized = TAKE_PTR(serialized);
4492 *ret_serialized_size = serialized_size;
4493
4494 return 0;
4495 }
4496
4497 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
4498 * across restarts of the TPM or reboots (assuming the handle is persistent). */
4499 int tpm2_serialize(
4500 Tpm2Context *c,
4501 const Tpm2Handle *handle,
4502 void **ret_serialized,
4503 size_t *ret_serialized_size) {
4504
4505 TSS2_RC rc;
4506
4507 assert(c);
4508 assert(handle);
4509 assert(ret_serialized);
4510 assert(ret_serialized_size);
4511
4512 _cleanup_(Esys_Freep) unsigned char *serialized = NULL;
4513 size_t size = 0;
4514 rc = sym_Esys_TR_Serialize(c->esys_context, handle->esys_handle, &serialized, &size);
4515 if (rc != TSS2_RC_SUCCESS)
4516 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4517 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc));
4518
4519 *ret_serialized = TAKE_PTR(serialized);
4520 *ret_serialized_size = size;
4521
4522 return 0;
4523 }
4524
4525 int tpm2_deserialize(
4526 Tpm2Context *c,
4527 const void *serialized,
4528 size_t serialized_size,
4529 Tpm2Handle **ret_handle) {
4530
4531 TSS2_RC rc;
4532 int r;
4533
4534 assert(c);
4535 assert(serialized);
4536 assert(ret_handle);
4537
4538 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
4539 r = tpm2_handle_new(c, &handle);
4540 if (r < 0)
4541 return r;
4542
4543 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
4544 handle->flush = false;
4545
4546 rc = sym_Esys_TR_Deserialize(c->esys_context, serialized, serialized_size, &handle->esys_handle);
4547 if (rc != TSS2_RC_SUCCESS)
4548 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4549 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc));
4550
4551 *ret_handle = TAKE_PTR(handle);
4552
4553 return 0;
4554 }
4555
4556 #if HAVE_OPENSSL
4557
4558 /* KDFa() as defined by the TPM spec. */
4559 static int tpm2_kdfa(
4560 TPMI_ALG_HASH hash_alg,
4561 const void *key,
4562 size_t key_len,
4563 const char *label,
4564 const void *context,
4565 size_t context_len,
4566 size_t bits,
4567 void **ret_key,
4568 size_t *ret_key_len) {
4569
4570 int r;
4571
4572 assert(key);
4573 assert(label);
4574 assert(context || context_len == 0);
4575 assert(bits > 0);
4576 assert(bits <= SIZE_MAX - 7);
4577 assert(ret_key);
4578 assert(ret_key_len);
4579
4580 log_debug("Calculating KDFa().");
4581
4582 size_t len = DIV_ROUND_UP(bits, 8);
4583
4584 const char *hash_alg_name = tpm2_hash_alg_to_string(hash_alg);
4585 if (!hash_alg_name)
4586 return -EOPNOTSUPP;
4587
4588 _cleanup_free_ void *buf = NULL;
4589 r = kdf_kb_hmac_derive(
4590 "COUNTER",
4591 hash_alg_name,
4592 key,
4593 key_len,
4594 label,
4595 strlen(label),
4596 context,
4597 context_len,
4598 /* seed= */ NULL,
4599 /* seed_len= */ 0,
4600 len,
4601 &buf);
4602 if (r < 0)
4603 return r;
4604
4605 /* If the number of bits results in a partial byte, the TPM spec requires we zero the unrequested
4606 * bits in the MSB (i.e. at index 0). From the spec Part 1 ("Architecture") section on Key
4607 * Derivation Function, specifically KDFa():
4608 *
4609 * "The implied return from this function is a sequence of octets with a length equal to (bits + 7) /
4610 * 8. If bits is not an even multiple of 8, then the returned value occupies the least significant
4611 * bits of the returned octet array, and the additional, high-order bits in the 0th octet are
4612 * CLEAR. The unused bits of the most significant octet (MSO) are masked off and not shifted." */
4613 size_t partial = bits % 8;
4614 if (partial > 0)
4615 ((uint8_t*) buf)[0] &= 0xffu >> (8 - partial);
4616
4617 *ret_key = TAKE_PTR(buf);
4618 *ret_key_len = len;
4619
4620 return 0;
4621 }
4622
4623 /* KDFe() as defined by the TPM spec. */
4624 static int tpm2_kdfe(
4625 TPMI_ALG_HASH hash_alg,
4626 const void *shared_secret,
4627 size_t shared_secret_len,
4628 const char *label,
4629 const void *context_u,
4630 size_t context_u_size,
4631 const void *context_v,
4632 size_t context_v_size,
4633 size_t bits,
4634 void **ret_key,
4635 size_t *ret_key_len) {
4636
4637 int r;
4638
4639 assert(shared_secret);
4640 assert(label);
4641 assert(context_u);
4642 assert(context_v);
4643 assert(bits > 0);
4644 assert(bits <= SIZE_MAX - 7);
4645 assert(ret_key);
4646 assert(ret_key_len);
4647
4648 log_debug("Calculating KDFe().");
4649
4650 size_t len = DIV_ROUND_UP(bits, 8);
4651
4652 const char *hash_alg_name = tpm2_hash_alg_to_string(hash_alg);
4653 if (!hash_alg_name)
4654 return -EOPNOTSUPP;
4655
4656 size_t info_len = strlen(label) + 1 + context_u_size + context_v_size;
4657 _cleanup_free_ void *info = malloc(info_len);
4658 if (!info)
4659 return log_oom_debug();
4660
4661 void *end = mempcpy(mempcpy(stpcpy(info, label) + 1, context_u, context_u_size), context_v, context_v_size);
4662 /* assert we copied exactly the right amount that we allocated */
4663 assert(end > info && (uintptr_t) end - (uintptr_t) info == info_len);
4664
4665 _cleanup_free_ void *buf = NULL;
4666 r = kdf_ss_derive(
4667 hash_alg_name,
4668 shared_secret,
4669 shared_secret_len,
4670 /* salt= */ NULL,
4671 /* salt_size= */ 0,
4672 info,
4673 info_len,
4674 len,
4675 &buf);
4676 if (r < 0)
4677 return r;
4678
4679 *ret_key = TAKE_PTR(buf);
4680 *ret_key_len = len;
4681
4682 return 0;
4683 }
4684
4685 static int tpm2_calculate_seal_public(
4686 const TPM2B_PUBLIC *parent,
4687 const TPMA_OBJECT *attributes,
4688 const TPM2B_DIGEST *policy,
4689 const TPM2B_DIGEST *seed,
4690 const void *secret,
4691 size_t secret_size,
4692 TPM2B_PUBLIC *ret) {
4693
4694 int r;
4695
4696 assert(parent);
4697 assert(seed);
4698 assert(secret);
4699 assert(ret);
4700
4701 log_debug("Calculating public part of sealed object.");
4702
4703 struct iovec data[] = {
4704 IOVEC_MAKE((void*) seed->buffer, seed->size),
4705 IOVEC_MAKE((void*) secret, secret_size),
4706 };
4707 TPM2B_DIGEST unique;
4708 r = tpm2_digest_many(
4709 parent->publicArea.nameAlg,
4710 &unique,
4711 data,
4712 ELEMENTSOF(data),
4713 /* extend= */ false);
4714 if (r < 0)
4715 return r;
4716
4717 *ret = (TPM2B_PUBLIC) {
4718 .size = sizeof(TPMT_PUBLIC),
4719 .publicArea = {
4720 .type = TPM2_ALG_KEYEDHASH,
4721 .nameAlg = parent->publicArea.nameAlg,
4722 .objectAttributes = attributes ? *attributes : 0,
4723 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, unique.size),
4724 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
4725 .unique.keyedHash = unique,
4726 },
4727 };
4728
4729 return 0;
4730 }
4731
4732 static int tpm2_calculate_seal_private(
4733 const TPM2B_PUBLIC *parent,
4734 const TPM2B_NAME *name,
4735 const char *pin,
4736 const TPM2B_DIGEST *seed,
4737 const void *secret,
4738 size_t secret_size,
4739 TPM2B_PRIVATE *ret) {
4740
4741 TSS2_RC rc;
4742 int r;
4743
4744 assert(parent);
4745 assert(name);
4746 assert(seed);
4747 assert(secret);
4748 assert(ret);
4749
4750 log_debug("Calculating private part of sealed object.");
4751
4752 _cleanup_free_ void *storage_key = NULL;
4753 size_t storage_key_size;
4754 r = tpm2_kdfa(parent->publicArea.nameAlg,
4755 seed->buffer,
4756 seed->size,
4757 "STORAGE",
4758 name->name,
4759 name->size,
4760 (size_t) parent->publicArea.parameters.asymDetail.symmetric.keyBits.sym,
4761 &storage_key,
4762 &storage_key_size);
4763 if (r < 0)
4764 return log_debug_errno(r, "Could not calculate storage key KDFa: %m");
4765
4766 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
4767 if (r < 0)
4768 return -EOPNOTSUPP;
4769
4770 size_t bits = (size_t) r * 8;
4771
4772 _cleanup_free_ void *integrity_key = NULL;
4773 size_t integrity_key_size;
4774 r = tpm2_kdfa(parent->publicArea.nameAlg,
4775 seed->buffer,
4776 seed->size,
4777 "INTEGRITY",
4778 /* context= */ NULL,
4779 /* n_context= */ 0,
4780 bits,
4781 &integrity_key,
4782 &integrity_key_size);
4783 if (r < 0)
4784 return log_debug_errno(r, "Could not calculate integrity key KDFa: %m");
4785
4786 TPM2B_AUTH auth = {};
4787 if (pin) {
4788 r = tpm2_get_pin_auth(parent->publicArea.nameAlg, pin, &auth);
4789 if (r < 0)
4790 return r;
4791 }
4792
4793 TPM2B_SENSITIVE sensitive = {
4794 .size = sizeof(TPMT_SENSITIVE),
4795 .sensitiveArea = {
4796 .sensitiveType = TPM2_ALG_KEYEDHASH,
4797 .authValue = auth,
4798 .seedValue = *seed,
4799 .sensitive.bits = TPM2B_SENSITIVE_DATA_MAKE(secret, secret_size),
4800 },
4801 };
4802
4803 _cleanup_free_ void *marshalled_sensitive = malloc(sizeof(sensitive));
4804 if (!marshalled_sensitive)
4805 return log_oom_debug();
4806
4807 size_t marshalled_sensitive_size = 0;
4808 rc = sym_Tss2_MU_TPM2B_SENSITIVE_Marshal(
4809 &sensitive,
4810 marshalled_sensitive,
4811 sizeof(sensitive),
4812 &marshalled_sensitive_size);
4813 if (rc != TSS2_RC_SUCCESS)
4814 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4815 "Failed to marshal sensitive: %s", sym_Tss2_RC_Decode(rc));
4816
4817 const char *sym_alg = tpm2_sym_alg_to_string(parent->publicArea.parameters.asymDetail.symmetric.algorithm);
4818 if (!sym_alg)
4819 return -EOPNOTSUPP;
4820
4821 const char *sym_mode = tpm2_sym_mode_to_string(parent->publicArea.parameters.asymDetail.symmetric.mode.sym);
4822 if (!sym_mode)
4823 return -EOPNOTSUPP;
4824
4825 _cleanup_free_ void *encrypted_sensitive = NULL;
4826 size_t encrypted_sensitive_size;
4827 r = openssl_cipher(
4828 sym_alg,
4829 parent->publicArea.parameters.asymDetail.symmetric.keyBits.sym,
4830 sym_mode,
4831 storage_key, storage_key_size,
4832 /* iv= */ NULL, /* n_iv= */ 0,
4833 marshalled_sensitive, marshalled_sensitive_size,
4834 &encrypted_sensitive, &encrypted_sensitive_size);
4835 if (r < 0)
4836 return r;
4837
4838 const char *hash_alg_name = tpm2_hash_alg_to_string(parent->publicArea.nameAlg);
4839 if (!hash_alg_name)
4840 return -EOPNOTSUPP;
4841
4842 _cleanup_free_ void *hmac_buffer = NULL;
4843 size_t hmac_size = 0;
4844 struct iovec hmac_data[] = {
4845 IOVEC_MAKE((void*) encrypted_sensitive, encrypted_sensitive_size),
4846 IOVEC_MAKE((void*) name->name, name->size),
4847 };
4848 r = openssl_hmac_many(
4849 hash_alg_name,
4850 integrity_key,
4851 integrity_key_size,
4852 hmac_data,
4853 ELEMENTSOF(hmac_data),
4854 &hmac_buffer,
4855 &hmac_size);
4856 if (r < 0)
4857 return r;
4858
4859 TPM2B_DIGEST outer_hmac = TPM2B_DIGEST_MAKE(hmac_buffer, hmac_size);
4860
4861 TPM2B_PRIVATE private = {};
4862 size_t private_size = 0;
4863 rc = sym_Tss2_MU_TPM2B_DIGEST_Marshal(
4864 &outer_hmac,
4865 private.buffer,
4866 sizeof(private.buffer),
4867 &private_size);
4868 if (rc != TSS2_RC_SUCCESS)
4869 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4870 "Failed to marshal digest: %s", sym_Tss2_RC_Decode(rc));
4871 private.size = private_size;
4872
4873 assert(sizeof(private.buffer) - private.size >= encrypted_sensitive_size);
4874 memcpy_safe(&private.buffer[private.size], encrypted_sensitive, encrypted_sensitive_size);
4875 private.size += encrypted_sensitive_size;
4876
4877 *ret = private;
4878
4879 return 0;
4880 }
4881
4882 static int tpm2_calculate_seal_rsa_seed(
4883 const TPM2B_PUBLIC *parent,
4884 void **ret_seed,
4885 size_t *ret_seed_size,
4886 void **ret_encrypted_seed,
4887 size_t *ret_encrypted_seed_size) {
4888
4889 int r;
4890
4891 assert(parent);
4892 assert(ret_seed);
4893 assert(ret_seed_size);
4894 assert(ret_encrypted_seed);
4895 assert(ret_encrypted_seed_size);
4896
4897 log_debug("Calculating encrypted seed for RSA sealed object.");
4898
4899 _cleanup_(EVP_PKEY_freep) EVP_PKEY *parent_pkey = NULL;
4900 r = tpm2_tpm2b_public_to_openssl_pkey(parent, &parent_pkey);
4901 if (r < 0)
4902 return log_debug_errno(r, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4903
4904 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
4905 if (r < 0)
4906 return -EOPNOTSUPP;
4907
4908 size_t seed_size = (size_t) r;
4909
4910 _cleanup_free_ void *seed = malloc(seed_size);
4911 if (!seed)
4912 return log_oom_debug();
4913
4914 r = crypto_random_bytes(seed, seed_size);
4915 if (r < 0)
4916 return log_debug_errno(r, "Failed to generate random seed: %m");
4917
4918 const char *hash_alg_name = tpm2_hash_alg_to_string(parent->publicArea.nameAlg);
4919 if (!hash_alg_name)
4920 return -EOPNOTSUPP;
4921
4922 _cleanup_free_ void *encrypted_seed = NULL;
4923 size_t encrypted_seed_size;
4924 r = rsa_oaep_encrypt_bytes(
4925 parent_pkey,
4926 hash_alg_name,
4927 "DUPLICATE",
4928 seed,
4929 seed_size,
4930 &encrypted_seed,
4931 &encrypted_seed_size);
4932 if (r < 0)
4933 return log_debug_errno(r, "Could not RSA-OAEP encrypt random seed: %m");
4934
4935 *ret_seed = TAKE_PTR(seed);
4936 *ret_seed_size = seed_size;
4937 *ret_encrypted_seed = TAKE_PTR(encrypted_seed);
4938 *ret_encrypted_seed_size = encrypted_seed_size;
4939
4940 return 0;
4941 }
4942
4943 static int tpm2_calculate_seal_ecc_seed(
4944 const TPM2B_PUBLIC *parent,
4945 void **ret_seed,
4946 size_t *ret_seed_size,
4947 void **ret_encrypted_seed,
4948 size_t *ret_encrypted_seed_size) {
4949
4950 TSS2_RC rc;
4951 int r;
4952
4953 assert(parent);
4954 assert(ret_seed);
4955 assert(ret_seed_size);
4956 assert(ret_encrypted_seed);
4957 assert(ret_encrypted_seed_size);
4958
4959 log_debug("Calculating encrypted seed for ECC sealed object.");
4960
4961 _cleanup_(EVP_PKEY_freep) EVP_PKEY *parent_pkey = NULL;
4962 r = tpm2_tpm2b_public_to_openssl_pkey(parent, &parent_pkey);
4963 if (r < 0)
4964 return log_debug_errno(r, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4965
4966 int curve_id;
4967 r = ecc_pkey_to_curve_x_y(
4968 parent_pkey,
4969 &curve_id,
4970 /* ret_x= */ NULL, /* ret_x_size= */ 0,
4971 /* ret_y= */ NULL, /* ret_y_size= */ 0);
4972 if (r < 0)
4973 return r;
4974
4975 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4976 r = ecc_pkey_new(curve_id, &pkey);
4977 if (r < 0)
4978 return r;
4979
4980 _cleanup_free_ void *shared_secret = NULL;
4981 size_t shared_secret_size;
4982 r = ecc_ecdh(pkey, parent_pkey, &shared_secret, &shared_secret_size);
4983 if (r < 0)
4984 return log_debug_errno(r, "Could not generate ECC shared secret: %m");
4985
4986 _cleanup_free_ void *x = NULL, *y = NULL;
4987 size_t x_size, y_size;
4988 r = ecc_pkey_to_curve_x_y(pkey, /* curve_id= */ NULL, &x, &x_size, &y, &y_size);
4989 if (r < 0)
4990 return log_debug_errno(r, "Could not get ECC get x/y: %m");
4991
4992 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
4993 if (r < 0)
4994 return log_debug_errno(r, "ECC point x size %zu is too large: %m", x_size);
4995
4996 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
4997 if (r < 0)
4998 return log_debug_errno(r, "ECC point y size %zu is too large: %m", y_size);
4999
5000 TPMS_ECC_POINT point = {
5001 .x = TPM2B_ECC_PARAMETER_MAKE(x, x_size),
5002 .y = TPM2B_ECC_PARAMETER_MAKE(y, y_size),
5003 };
5004
5005 _cleanup_free_ void *encrypted_seed = malloc(sizeof(point));
5006 if (!encrypted_seed)
5007 return log_oom_debug();
5008
5009 size_t encrypted_seed_size = 0;
5010 rc = sym_Tss2_MU_TPMS_ECC_POINT_Marshal(&point, encrypted_seed, sizeof(point), &encrypted_seed_size);
5011 if (rc != TPM2_RC_SUCCESS)
5012 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5013 "Failed to marshal ECC point: %s", sym_Tss2_RC_Decode(rc));
5014
5015 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
5016 if (r < 0)
5017 return -EOPNOTSUPP;
5018
5019 size_t bits = (size_t) r * 8;
5020
5021 _cleanup_free_ void *seed = NULL;
5022 size_t seed_size = 0; /* Explicit initialization to appease gcc */
5023 r = tpm2_kdfe(parent->publicArea.nameAlg,
5024 shared_secret,
5025 shared_secret_size,
5026 "DUPLICATE",
5027 x,
5028 x_size,
5029 parent->publicArea.unique.ecc.x.buffer,
5030 parent->publicArea.unique.ecc.x.size,
5031 bits,
5032 &seed,
5033 &seed_size);
5034 if (r < 0)
5035 return log_debug_errno(r, "Could not calculate KDFe: %m");
5036
5037 *ret_seed = TAKE_PTR(seed);
5038 *ret_seed_size = seed_size;
5039 *ret_encrypted_seed = TAKE_PTR(encrypted_seed);
5040 *ret_encrypted_seed_size = encrypted_seed_size;
5041
5042 return 0;
5043 }
5044
5045 static int tpm2_calculate_seal_seed(
5046 const TPM2B_PUBLIC *parent,
5047 TPM2B_DIGEST *ret_seed,
5048 TPM2B_ENCRYPTED_SECRET *ret_encrypted_seed) {
5049
5050 int r;
5051
5052 assert(parent);
5053 assert(ret_seed);
5054 assert(ret_encrypted_seed);
5055
5056 log_debug("Calculating encrypted seed for sealed object.");
5057
5058 _cleanup_free_ void *seed = NULL, *encrypted_seed = NULL;
5059 size_t seed_size = 0, encrypted_seed_size = 0; /* Explicit initialization to appease gcc */
5060 if (parent->publicArea.type == TPM2_ALG_RSA)
5061 r = tpm2_calculate_seal_rsa_seed(parent, &seed, &seed_size, &encrypted_seed, &encrypted_seed_size);
5062 else if (parent->publicArea.type == TPM2_ALG_ECC)
5063 r = tpm2_calculate_seal_ecc_seed(parent, &seed, &seed_size, &encrypted_seed, &encrypted_seed_size);
5064 else
5065 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5066 "Unsupported parent key type 0x%" PRIx16, parent->publicArea.type);
5067 if (r < 0)
5068 return log_debug_errno(r, "Could not calculate encrypted seed: %m");
5069
5070 *ret_seed = TPM2B_DIGEST_MAKE(seed, seed_size);
5071 *ret_encrypted_seed = TPM2B_ENCRYPTED_SECRET_MAKE(encrypted_seed, encrypted_seed_size);
5072
5073 return 0;
5074 }
5075
5076 #endif /* HAVE_OPENSSL */
5077
5078 int tpm2_calculate_seal(
5079 TPM2_HANDLE parent_handle,
5080 const TPM2B_PUBLIC *parent_public,
5081 const TPMA_OBJECT *attributes,
5082 const struct iovec *secret,
5083 const TPM2B_DIGEST *policy,
5084 const char *pin,
5085 struct iovec *ret_secret,
5086 struct iovec *ret_blob,
5087 struct iovec *ret_serialized_parent) {
5088
5089 #if HAVE_OPENSSL
5090 int r;
5091
5092 assert(parent_public);
5093 assert(iovec_is_valid(secret));
5094 assert(secret || ret_secret);
5095 assert(!(secret && ret_secret)); /* Either provide a secret, or we create one, but not both */
5096 assert(ret_blob);
5097 assert(ret_serialized_parent);
5098
5099 log_debug("Calculating sealed object.");
5100
5101 /* Default to the SRK. */
5102 if (parent_handle == 0)
5103 parent_handle = TPM2_SRK_HANDLE;
5104
5105 switch (TPM2_HANDLE_TYPE(parent_handle)) {
5106 case TPM2_HT_PERSISTENT:
5107 case TPM2_HT_NV_INDEX:
5108 break;
5109 case TPM2_HT_TRANSIENT:
5110 log_warning("Handle is transient, sealed secret may not be recoverable.");
5111 break;
5112 default:
5113 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5114 "Handle 0x%" PRIx32 " not persistent, transient, or NV.",
5115 parent_handle);
5116 }
5117
5118 _cleanup_(iovec_done_erase) struct iovec generated_secret = {};
5119 if (!secret) {
5120 /* No secret provided, generate a random secret. We use SHA256 digest length, though it can
5121 * be up to TPM2_MAX_SEALED_DATA. The secret length is not limited to the nameAlg hash
5122 * size. */
5123 generated_secret.iov_len = TPM2_SHA256_DIGEST_SIZE;
5124 generated_secret.iov_base = malloc(generated_secret.iov_len);
5125 if (!generated_secret.iov_base)
5126 return log_oom_debug();
5127
5128 r = crypto_random_bytes(generated_secret.iov_base, generated_secret.iov_len);
5129 if (r < 0)
5130 return log_debug_errno(r, "Failed to generate secret key: %m");
5131
5132 secret = &generated_secret;
5133 }
5134
5135 if (secret->iov_len > TPM2_MAX_SEALED_DATA)
5136 return log_debug_errno(SYNTHETIC_ERRNO(EOVERFLOW),
5137 "Secret size %zu too large, limit is %d bytes.",
5138 secret->iov_len, TPM2_MAX_SEALED_DATA);
5139
5140 TPM2B_DIGEST random_seed;
5141 TPM2B_ENCRYPTED_SECRET seed;
5142 r = tpm2_calculate_seal_seed(parent_public, &random_seed, &seed);
5143 if (r < 0)
5144 return r;
5145
5146 TPM2B_PUBLIC public;
5147 r = tpm2_calculate_seal_public(parent_public, attributes, policy, &random_seed, secret->iov_base, secret->iov_len, &public);
5148 if (r < 0)
5149 return r;
5150
5151 TPM2B_NAME name;
5152 r = tpm2_calculate_pubkey_name(&public.publicArea, &name);
5153 if (r < 0)
5154 return r;
5155
5156 TPM2B_PRIVATE private;
5157 r = tpm2_calculate_seal_private(parent_public, &name, pin, &random_seed, secret->iov_base, secret->iov_len, &private);
5158 if (r < 0)
5159 return r;
5160
5161 _cleanup_(iovec_done) struct iovec blob = {};
5162 r = tpm2_marshal_blob(&public, &private, &seed, &blob.iov_base, &blob.iov_len);
5163 if (r < 0)
5164 return log_debug_errno(r, "Could not create sealed blob: %m");
5165
5166 TPM2B_NAME parent_name;
5167 r = tpm2_calculate_pubkey_name(&parent_public->publicArea, &parent_name);
5168 if (r < 0)
5169 return r;
5170
5171 _cleanup_(iovec_done) struct iovec serialized_parent = {};
5172 r = tpm2_calculate_serialize(
5173 parent_handle,
5174 &parent_name,
5175 parent_public,
5176 &serialized_parent.iov_base,
5177 &serialized_parent.iov_len);
5178 if (r < 0)
5179 return r;
5180
5181 if (ret_secret)
5182 *ret_secret = TAKE_STRUCT(generated_secret);
5183 *ret_blob = TAKE_STRUCT(blob);
5184 *ret_serialized_parent = TAKE_STRUCT(serialized_parent);
5185
5186 return 0;
5187 #else /* HAVE_OPENSSL */
5188 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
5189 #endif
5190 }
5191
5192 int tpm2_seal(Tpm2Context *c,
5193 uint32_t seal_key_handle,
5194 const TPM2B_DIGEST *policy,
5195 const char *pin,
5196 struct iovec *ret_secret,
5197 struct iovec *ret_blob,
5198 uint16_t *ret_primary_alg,
5199 struct iovec *ret_srk) {
5200
5201 uint16_t primary_alg = 0;
5202 int r;
5203
5204 assert(ret_secret);
5205 assert(ret_blob);
5206
5207 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
5208 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
5209 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
5210 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
5211 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
5212 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
5213 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
5214 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
5215 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
5216 * LUKS2 JSON header.
5217 *
5218 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
5219 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
5220 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
5221 * binding the unlocking to the TPM2 chip. */
5222
5223 usec_t start = now(CLOCK_MONOTONIC);
5224
5225 TPMA_OBJECT hmac_attributes =
5226 TPMA_OBJECT_FIXEDTPM |
5227 TPMA_OBJECT_FIXEDPARENT;
5228
5229 /* If protected by PIN, a user-selected low-entropy password, enable DA protection.
5230 Without a PIN, the key's left protected only by a PCR policy, which does not benefit
5231 from DA protection. */
5232 hmac_attributes |= pin ? 0 : TPMA_OBJECT_NODA;
5233
5234 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
5235 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
5236 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
5237 TPMT_PUBLIC hmac_template = {
5238 .type = TPM2_ALG_KEYEDHASH,
5239 .nameAlg = TPM2_ALG_SHA256,
5240 .objectAttributes = hmac_attributes,
5241 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
5242 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
5243 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
5244 };
5245
5246 TPMS_SENSITIVE_CREATE hmac_sensitive = {
5247 .data.size = hmac_template.unique.keyedHash.size,
5248 };
5249
5250 CLEANUP_ERASE(hmac_sensitive);
5251
5252 if (pin) {
5253 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &hmac_sensitive.userAuth);
5254 if (r < 0)
5255 return r;
5256 }
5257
5258 assert(sizeof(hmac_sensitive.data.buffer) >= hmac_sensitive.data.size);
5259
5260 (void) tpm2_credit_random(c);
5261
5262 log_debug("Generating secret key data.");
5263
5264 r = crypto_random_bytes(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
5265 if (r < 0)
5266 return log_debug_errno(r, "Failed to generate secret key: %m");
5267
5268 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
5269 if (ret_srk) {
5270 _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
5271
5272 if (IN_SET(seal_key_handle, 0, TPM2_SRK_HANDLE)) {
5273 r = tpm2_get_or_create_srk(
5274 c,
5275 /* session= */ NULL,
5276 &primary_public,
5277 /* ret_name= */ NULL,
5278 /* ret_qname= */ NULL,
5279 &primary_handle);
5280 if (r < 0)
5281 return r;
5282 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle), TPM2_HT_TRANSIENT, TPM2_HT_PERSISTENT)) {
5283 r = tpm2_index_to_handle(
5284 c,
5285 seal_key_handle,
5286 /* session= */ NULL,
5287 &primary_public,
5288 /* ret_name= */ NULL,
5289 /* ret_qname= */ NULL,
5290 &primary_handle);
5291 if (r < 0)
5292 return r;
5293 if (r == 0)
5294 /* We do NOT automatically create anything other than the SRK */
5295 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
5296 "No handle found at index 0x%" PRIx32, seal_key_handle);
5297 } else
5298 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5299 "Seal key handle 0x%" PRIx32 " is neither transient nor persistent.",
5300 seal_key_handle);
5301
5302 primary_alg = primary_public->publicArea.type;
5303 } else {
5304 if (seal_key_handle != 0)
5305 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
5306
5307 /* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
5308 primary_alg = TPM2_ALG_ECC;
5309
5310 TPM2B_PUBLIC template = {
5311 .size = sizeof(TPMT_PUBLIC),
5312 };
5313 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5314 if (r < 0)
5315 return log_debug_errno(r, "Could not get legacy ECC template: %m");
5316
5317 if (!tpm2_supports_tpmt_public(c, &template.publicArea)) {
5318 primary_alg = TPM2_ALG_RSA;
5319
5320 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5321 if (r < 0)
5322 return log_debug_errno(r, "Could not get legacy RSA template: %m");
5323
5324 if (!tpm2_supports_tpmt_public(c, &template.publicArea))
5325 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5326 "TPM does not support either ECC or RSA legacy template.");
5327 }
5328
5329 r = tpm2_create_primary(
5330 c,
5331 /* session= */ NULL,
5332 &template,
5333 /* sensitive= */ NULL,
5334 /* ret_public= */ NULL,
5335 &primary_handle);
5336 if (r < 0)
5337 return r;
5338 }
5339
5340 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
5341 r = tpm2_make_encryption_session(c, primary_handle, /* bind_key= */ NULL, &encryption_session);
5342 if (r < 0)
5343 return r;
5344
5345 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
5346 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
5347 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
5348 if (r < 0)
5349 return r;
5350
5351 _cleanup_(iovec_done_erase) struct iovec secret = {};
5352 secret.iov_base = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
5353 if (!secret.iov_base)
5354 return log_oom_debug();
5355 secret.iov_len = hmac_sensitive.data.size;
5356
5357 log_debug("Marshalling private and public part of HMAC key.");
5358
5359 _cleanup_(iovec_done) struct iovec blob = {};
5360 r = tpm2_marshal_blob(public, private, /* seed= */ NULL, &blob.iov_base, &blob.iov_len);
5361 if (r < 0)
5362 return log_debug_errno(r, "Could not create sealed blob: %m");
5363
5364 if (DEBUG_LOGGING)
5365 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5366
5367 if (ret_srk) {
5368 _cleanup_(iovec_done) struct iovec srk = {};
5369 _cleanup_(Esys_Freep) void *tmp = NULL;
5370 size_t tmp_size;
5371
5372 r = tpm2_serialize(c, primary_handle, &tmp, &tmp_size);
5373 if (r < 0)
5374 return r;
5375
5376 /*
5377 * make a copy since we don't want the caller to understand that
5378 * ESYS allocated the pointer. It would make tracking what deallocator
5379 * to use for srk in which context a PITA.
5380 */
5381 srk.iov_base = memdup(tmp, tmp_size);
5382 if (!srk.iov_base)
5383 return log_oom_debug();
5384 srk.iov_len = tmp_size;
5385
5386 *ret_srk = TAKE_STRUCT(srk);
5387 }
5388
5389 *ret_secret = TAKE_STRUCT(secret);
5390 *ret_blob = TAKE_STRUCT(blob);
5391
5392 if (ret_primary_alg)
5393 *ret_primary_alg = primary_alg;
5394
5395 return 0;
5396 }
5397
5398 #define RETRY_UNSEAL_MAX 30u
5399
5400 int tpm2_unseal(Tpm2Context *c,
5401 uint32_t hash_pcr_mask,
5402 uint16_t pcr_bank,
5403 const struct iovec *pubkey,
5404 uint32_t pubkey_pcr_mask,
5405 JsonVariant *signature,
5406 const char *pin,
5407 const Tpm2PCRLockPolicy *pcrlock_policy,
5408 uint16_t primary_alg,
5409 const struct iovec *blob,
5410 const struct iovec *known_policy_hash,
5411 const struct iovec *srk,
5412 struct iovec *ret_secret) {
5413
5414 TSS2_RC rc;
5415 int r;
5416
5417 assert(iovec_is_set(blob));
5418 assert(iovec_is_valid(known_policy_hash));
5419 assert(iovec_is_valid(pubkey));
5420 assert(ret_secret);
5421
5422 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
5423 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5424
5425 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
5426 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
5427 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
5428 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
5429 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
5430 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5431 * and use it to unlock the LUKS2 volume. */
5432
5433 usec_t start = now(CLOCK_MONOTONIC);
5434
5435 TPM2B_PUBLIC public;
5436 TPM2B_PRIVATE private;
5437 TPM2B_ENCRYPTED_SECRET seed = {};
5438 r = tpm2_unmarshal_blob(blob->iov_base, blob->iov_len, &public, &private, &seed);
5439 if (r < 0)
5440 return log_debug_errno(r, "Could not extract parts from blob: %m");
5441
5442 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
5443 * so we need to handle that legacy situation. */
5444 if (pcr_bank == UINT16_MAX) {
5445 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
5446 if (r < 0)
5447 return r;
5448 }
5449
5450 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
5451 if (iovec_is_set(srk)) {
5452 r = tpm2_deserialize(c, srk->iov_base, srk->iov_len, &primary_handle);
5453 if (r < 0)
5454 return r;
5455 } else if (primary_alg != 0) {
5456 TPM2B_PUBLIC template = {
5457 .size = sizeof(TPMT_PUBLIC),
5458 };
5459 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5460 if (r < 0)
5461 return log_debug_errno(r, "Could not get legacy template: %m");
5462
5463 r = tpm2_create_primary(
5464 c,
5465 /* session= */ NULL,
5466 &template,
5467 /* sensitive= */ NULL,
5468 /* ret_public= */ NULL,
5469 &primary_handle);
5470 if (r < 0)
5471 return r;
5472 } else
5473 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5474 "No SRK or primary alg provided.");
5475
5476 if (seed.size > 0) {
5477 /* This is a calculated (or duplicated) sealed object, and must be imported. */
5478 _cleanup_free_ TPM2B_PRIVATE *imported_private = NULL;
5479 r = tpm2_import(c,
5480 primary_handle,
5481 /* session= */ NULL,
5482 &public,
5483 &private,
5484 &seed,
5485 /* encryption_key= */ NULL,
5486 /* symmetric= */ NULL,
5487 &imported_private);
5488 if (r < 0)
5489 return r;
5490
5491 private = *imported_private;
5492 }
5493
5494 log_debug("Loading HMAC key into TPM.");
5495
5496 /*
5497 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
5498 * gives you back a different key, the session initiation will fail. In the
5499 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
5500 * provides protections.
5501 */
5502 _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
5503 r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
5504 if (r < 0)
5505 return r;
5506
5507 TPM2B_PUBLIC pubkey_tpm2b;
5508 _cleanup_(iovec_done) struct iovec fp = {};
5509 if (iovec_is_set(pubkey)) {
5510 r = tpm2_tpm2b_public_from_pem(pubkey->iov_base, pubkey->iov_len, &pubkey_tpm2b);
5511 if (r < 0)
5512 return log_debug_errno(r, "Could not create TPMT_PUBLIC: %m");
5513
5514 r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp.iov_base, &fp.iov_len);
5515 if (r < 0)
5516 return log_debug_errno(r, "Could not get key fingerprint: %m");
5517 }
5518
5519 /*
5520 * if a pin is set for the seal object, use it to bind the session
5521 * key to that object. This prevents active bus interposers from
5522 * faking a TPM and seeing the unsealed value. An active interposer
5523 * could fake a TPM, satisfying the encrypted session, and just
5524 * forward everything to the *real* TPM.
5525 */
5526 r = tpm2_set_auth(c, hmac_key, pin);
5527 if (r < 0)
5528 return r;
5529
5530 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
5531 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
5532 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
5533 r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
5534 if (r < 0)
5535 return r;
5536
5537 _cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
5538 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
5539 r = tpm2_make_policy_session(
5540 c,
5541 primary_handle,
5542 encryption_session,
5543 &policy_session);
5544 if (r < 0)
5545 return r;
5546
5547 r = tpm2_build_sealing_policy(
5548 c,
5549 policy_session,
5550 hash_pcr_mask,
5551 pcr_bank,
5552 iovec_is_set(pubkey) ? &pubkey_tpm2b : NULL,
5553 fp.iov_base, fp.iov_len,
5554 pubkey_pcr_mask,
5555 signature,
5556 !!pin,
5557 pcrlock_policy,
5558 &policy_digest);
5559 if (r < 0)
5560 return r;
5561
5562 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
5563 * wait until the TPM2 tells us to go away. */
5564 if (iovec_is_set(known_policy_hash) && memcmp_nn(policy_digest->buffer,
5565 policy_digest->size,
5566 known_policy_hash->iov_base,
5567 known_policy_hash->iov_len) != 0) {
5568 #if HAVE_OPENSSL
5569 if (iovec_is_set(pubkey) &&
5570 pubkey_tpm2b.publicArea.type == TPM2_ALG_RSA &&
5571 pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent == TPM2_RSA_DEFAULT_EXPONENT) {
5572 /* Due to bug #30546, if using RSA pubkey with the default exponent, we may
5573 * need to set the exponent to the TPM special-case value of 0 and retry. */
5574 log_debug("Policy hash mismatch, retrying with RSA pubkey exponent set to 0.");
5575 pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent = 0;
5576 continue;
5577 } else
5578 #endif
5579 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
5580 "Current policy digest does not match stored policy digest, cancelling "
5581 "TPM2 authentication attempt.");
5582 }
5583
5584 log_debug("Unsealing HMAC key.");
5585
5586 rc = sym_Esys_Unseal(
5587 c->esys_context,
5588 hmac_key->esys_handle,
5589 policy_session->esys_handle,
5590 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
5591 ESYS_TR_NONE,
5592 &unsealed);
5593 if (rc == TSS2_RC_SUCCESS)
5594 break;
5595 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
5596 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5597 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
5598 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5599 }
5600
5601 _cleanup_(iovec_done_erase) struct iovec secret = {};
5602 secret.iov_base = memdup(unsealed->buffer, unsealed->size);
5603 explicit_bzero_safe(unsealed->buffer, unsealed->size);
5604 if (!secret.iov_base)
5605 return log_oom_debug();
5606 secret.iov_len = unsealed->size;
5607
5608 if (DEBUG_LOGGING)
5609 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5610
5611 *ret_secret = TAKE_STRUCT(secret);
5612
5613 return 0;
5614 }
5615
5616 static TPM2_HANDLE generate_random_nv_index(void) {
5617 return TPM2_NV_INDEX_FIRST + (TPM2_HANDLE) random_u64_range(TPM2_NV_INDEX_LAST - TPM2_NV_INDEX_FIRST + 1);
5618 }
5619
5620 int tpm2_define_policy_nv_index(
5621 Tpm2Context *c,
5622 const Tpm2Handle *session,
5623 TPM2_HANDLE requested_nv_index,
5624 const TPM2B_DIGEST *write_policy,
5625 const char *pin,
5626 const TPM2B_AUTH *auth,
5627 TPM2_HANDLE *ret_nv_index,
5628 Tpm2Handle **ret_nv_handle,
5629 TPM2B_NV_PUBLIC *ret_nv_public) {
5630
5631 _cleanup_(tpm2_handle_freep) Tpm2Handle *new_handle = NULL;
5632 TSS2_RC rc;
5633 int r;
5634
5635 assert(c);
5636 assert(pin || auth);
5637
5638 r = tpm2_handle_new(c, &new_handle);
5639 if (r < 0)
5640 return r;
5641
5642 new_handle->flush = false; /* This is a persistent NV index, don't flush hence */
5643
5644 TPM2B_AUTH _auth = {};
5645 CLEANUP_ERASE(_auth);
5646
5647 if (!auth) {
5648 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &_auth);
5649 if (r < 0)
5650 return r;
5651
5652 auth = &_auth;
5653 }
5654
5655 for (unsigned try = 0; try < 25U; try++) {
5656 TPM2_HANDLE nv_index;
5657
5658 if (requested_nv_index != 0)
5659 nv_index = requested_nv_index;
5660 else
5661 nv_index = generate_random_nv_index();
5662
5663 TPM2B_NV_PUBLIC public_info = {
5664 .size = sizeof_field(TPM2B_NV_PUBLIC, nvPublic),
5665 .nvPublic = {
5666 .nvIndex = nv_index,
5667 .nameAlg = TPM2_ALG_SHA256,
5668 .attributes = TPM2_NT_ORDINARY | TPMA_NV_WRITEALL | TPMA_NV_POLICYWRITE | TPMA_NV_OWNERREAD,
5669 .dataSize = offsetof(TPMT_HA, digest) + tpm2_hash_alg_to_size(TPM2_ALG_SHA256),
5670 },
5671 };
5672
5673 if (write_policy)
5674 public_info.nvPublic.authPolicy = *write_policy;
5675
5676 rc = sym_Esys_NV_DefineSpace(
5677 c->esys_context,
5678 /* authHandle= */ ESYS_TR_RH_OWNER,
5679 /* shandle1= */ session ? session->esys_handle : ESYS_TR_PASSWORD,
5680 /* shandle2= */ ESYS_TR_NONE,
5681 /* shandle3= */ ESYS_TR_NONE,
5682 auth,
5683 &public_info,
5684 &new_handle->esys_handle);
5685
5686 if (rc == TSS2_RC_SUCCESS) {
5687 log_debug("NV Index 0x%" PRIx32 " successfully allocated.", nv_index);
5688
5689 if (ret_nv_index)
5690 *ret_nv_index = nv_index;
5691
5692 if (ret_nv_handle)
5693 *ret_nv_handle = TAKE_PTR(new_handle);
5694
5695 if (ret_nv_public)
5696 *ret_nv_public = public_info;
5697
5698 return 0;
5699 }
5700 if (rc != TPM2_RC_NV_DEFINED)
5701 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5702 "Failed to allocate NV index: %s", sym_Tss2_RC_Decode(rc));
5703
5704 if (requested_nv_index != 0) {
5705 assert(nv_index == requested_nv_index);
5706 return log_debug_errno(SYNTHETIC_ERRNO(EEXIST),
5707 "Requested NV index 0x%" PRIx32 " already taken.", requested_nv_index);
5708 }
5709
5710 log_debug("NV index 0x%" PRIu32 " already taken, trying another one (%u tries left)", nv_index, try);
5711 }
5712
5713 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5714 "Too many attempts trying to allocate NV index: %s", sym_Tss2_RC_Decode(rc));
5715 }
5716
5717 int tpm2_write_policy_nv_index(
5718 Tpm2Context *c,
5719 const Tpm2Handle *policy_session,
5720 TPM2_HANDLE nv_index,
5721 const Tpm2Handle *nv_handle,
5722 const TPM2B_DIGEST *policy_digest) {
5723
5724 TSS2_RC rc;
5725
5726 assert(c);
5727 assert(policy_session);
5728 assert(nv_handle);
5729 assert(policy_digest);
5730
5731 if (policy_digest->size != tpm2_hash_alg_to_size(TPM2_ALG_SHA256))
5732 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Policy to store in NV index has wrong size.");
5733
5734 TPMT_HA ha = {
5735 .hashAlg = TPM2_ALG_SHA256,
5736 };
5737 assert(policy_digest->size <= sizeof_field(TPMT_HA, digest));
5738 memcpy_safe(&ha.digest, policy_digest->buffer, policy_digest->size);
5739
5740 TPM2B_MAX_NV_BUFFER buffer = {};
5741 size_t written = 0;
5742 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, buffer.buffer, sizeof(buffer.buffer), &written);
5743 if (rc != TSS2_RC_SUCCESS)
5744 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5745 "Failed to marshal policy digest.");
5746
5747 buffer.size = written;
5748
5749 rc = sym_Esys_NV_Write(
5750 c->esys_context,
5751 /* authHandle= */ nv_handle->esys_handle,
5752 /* nvIndex= */ nv_handle->esys_handle,
5753 /* shandle1= */ policy_session->esys_handle,
5754 /* shandle2= */ ESYS_TR_NONE,
5755 /* shandle3= */ ESYS_TR_NONE,
5756 &buffer,
5757 /* offset= */ 0);
5758 if (rc != TSS2_RC_SUCCESS)
5759 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5760 "Failed to write NV index: %s", sym_Tss2_RC_Decode(rc));
5761
5762 if (DEBUG_LOGGING) {
5763 _cleanup_free_ char *h = NULL;
5764 h = hexmem(policy_digest->buffer, policy_digest->size);
5765 log_debug("Written policy digest %s to NV index 0x%x", strnull(h), nv_index);
5766 }
5767
5768 return 0;
5769 }
5770
5771 int tpm2_undefine_policy_nv_index(
5772 Tpm2Context *c,
5773 const Tpm2Handle *session,
5774 TPM2_HANDLE nv_index,
5775 const Tpm2Handle *nv_handle) {
5776
5777 TSS2_RC rc;
5778
5779 assert(c);
5780 assert(nv_handle);
5781
5782 rc = sym_Esys_NV_UndefineSpace(
5783 c->esys_context,
5784 /* authHandle= */ ESYS_TR_RH_OWNER,
5785 /* nvIndex= */ nv_handle->esys_handle,
5786 /* shandle1= */ session ? session->esys_handle : ESYS_TR_NONE,
5787 /* shandle2= */ ESYS_TR_NONE,
5788 /* shandle3= */ ESYS_TR_NONE);
5789 if (rc != TSS2_RC_SUCCESS)
5790 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5791 "Failed to undefine NV index: %s", sym_Tss2_RC_Decode(rc));
5792
5793 log_debug("Undefined NV index 0x%x", nv_index);
5794 return 0;
5795 }
5796
5797 int tpm2_seal_data(
5798 Tpm2Context *c,
5799 const struct iovec *data,
5800 const Tpm2Handle *primary_handle,
5801 const Tpm2Handle *encryption_session,
5802 const TPM2B_DIGEST *policy,
5803 struct iovec *ret_public,
5804 struct iovec *ret_private) {
5805
5806 int r;
5807
5808 assert(c);
5809 assert(data);
5810 assert(primary_handle);
5811
5812 /* This is a generic version of tpm2_seal(), that doesn't imply any policy or any specific
5813 * combination of the two keypairs in their marshalling. tpm2_seal() is somewhat specific to the FDE
5814 * usecase. We probably should migrate tpm2_seal() to use tpm2_seal_data() eventually. */
5815
5816 if (data->iov_len >= sizeof_field(TPMS_SENSITIVE_CREATE, data.buffer))
5817 return -E2BIG;
5818
5819 TPMT_PUBLIC hmac_template = {
5820 .type = TPM2_ALG_KEYEDHASH,
5821 .nameAlg = TPM2_ALG_SHA256,
5822 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
5823 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
5824 .unique.keyedHash.size = data->iov_len,
5825 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
5826 };
5827
5828 TPMS_SENSITIVE_CREATE hmac_sensitive = {
5829 .data.size = hmac_template.unique.keyedHash.size,
5830 };
5831
5832 CLEANUP_ERASE(hmac_sensitive);
5833
5834 memcpy_safe(hmac_sensitive.data.buffer, data->iov_base, data->iov_len);
5835
5836 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
5837 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
5838 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
5839 if (r < 0)
5840 return r;
5841
5842 _cleanup_(iovec_done) struct iovec public_blob = {}, private_blob = {};
5843
5844 r = tpm2_marshal_private(private, &private_blob.iov_base, &private_blob.iov_len);
5845 if (r < 0)
5846 return r;
5847
5848 r = tpm2_marshal_public(public, &public_blob.iov_base, &public_blob.iov_len);
5849 if (r < 0)
5850 return r;
5851
5852 if (ret_public)
5853 *ret_public = TAKE_STRUCT(public_blob);
5854 if (ret_private)
5855 *ret_private = TAKE_STRUCT(private_blob);
5856
5857 return 0;
5858 }
5859
5860 int tpm2_unseal_data(
5861 Tpm2Context *c,
5862 const struct iovec *public_blob,
5863 const struct iovec *private_blob,
5864 const Tpm2Handle *primary_handle,
5865 const Tpm2Handle *policy_session,
5866 const Tpm2Handle *encryption_session,
5867 struct iovec *ret_data) {
5868
5869 TSS2_RC rc;
5870 int r;
5871
5872 assert(c);
5873 assert(public_blob);
5874 assert(private_blob);
5875 assert(primary_handle);
5876
5877 TPM2B_PUBLIC public;
5878 r = tpm2_unmarshal_public(public_blob->iov_base, public_blob->iov_len, &public);
5879 if (r < 0)
5880 return r;
5881
5882 TPM2B_PRIVATE private;
5883 r = tpm2_unmarshal_private(private_blob->iov_base, private_blob->iov_len, &private);
5884 if (r < 0)
5885 return r;
5886
5887 _cleanup_(tpm2_handle_freep) Tpm2Handle *what = NULL;
5888 r = tpm2_load(c, primary_handle, NULL, &public, &private, &what);
5889 if (r < 0)
5890 return r;
5891
5892 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
5893 rc = sym_Esys_Unseal(
5894 c->esys_context,
5895 what->esys_handle,
5896 policy_session ? policy_session->esys_handle : ESYS_TR_NONE,
5897 encryption_session ? encryption_session->esys_handle : ESYS_TR_NONE,
5898 ESYS_TR_NONE,
5899 &unsealed);
5900 if (rc == TPM2_RC_PCR_CHANGED)
5901 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE),
5902 "PCR changed while unsealing.");
5903 if (rc != TSS2_RC_SUCCESS)
5904 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5905 "Failed to unseal data: %s", sym_Tss2_RC_Decode(rc));
5906
5907 _cleanup_(iovec_done) struct iovec d = {};
5908 d = IOVEC_MAKE(memdup(unsealed->buffer, unsealed->size), unsealed->size);
5909
5910 explicit_bzero_safe(unsealed->buffer, unsealed->size);
5911
5912 if (!d.iov_base)
5913 return log_oom_debug();
5914
5915 *ret_data = TAKE_STRUCT(d);
5916 return 0;
5917 }
5918 #endif /* HAVE_TPM2 */
5919
5920 int tpm2_list_devices(void) {
5921 #if HAVE_TPM2
5922 _cleanup_(table_unrefp) Table *t = NULL;
5923 _cleanup_closedir_ DIR *d = NULL;
5924 int r;
5925
5926 r = dlopen_tpm2();
5927 if (r < 0)
5928 return log_error_errno(r, "TPM2 support is not installed.");
5929
5930 t = table_new("path", "device", "driver");
5931 if (!t)
5932 return log_oom();
5933
5934 d = opendir("/sys/class/tpmrm");
5935 if (!d) {
5936 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
5937 if (errno != ENOENT)
5938 return -errno;
5939 } else {
5940 for (;;) {
5941 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
5942 struct dirent *de;
5943
5944 de = readdir_no_dot(d);
5945 if (!de)
5946 break;
5947
5948 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
5949 if (!device_path)
5950 return log_oom();
5951
5952 r = readlink_malloc(device_path, &device);
5953 if (r < 0)
5954 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
5955 else {
5956 driver_path = path_join(device_path, "driver");
5957 if (!driver_path)
5958 return log_oom();
5959
5960 r = readlink_malloc(driver_path, &driver);
5961 if (r < 0)
5962 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
5963 }
5964
5965 node = path_join("/dev", de->d_name);
5966 if (!node)
5967 return log_oom();
5968
5969 r = table_add_many(
5970 t,
5971 TABLE_PATH, node,
5972 TABLE_STRING, device ? last_path_component(device) : NULL,
5973 TABLE_STRING, driver ? last_path_component(driver) : NULL);
5974 if (r < 0)
5975 return table_log_add_error(r);
5976 }
5977 }
5978
5979 if (table_isempty(t)) {
5980 log_info("No suitable TPM2 devices found.");
5981 return 0;
5982 }
5983
5984 r = table_print(t, stdout);
5985 if (r < 0)
5986 return log_error_errno(r, "Failed to show device table: %m");
5987
5988 return 0;
5989 #else
5990 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5991 "TPM2 not supported on this build.");
5992 #endif
5993 }
5994
5995 int tpm2_find_device_auto(char **ret) {
5996 #if HAVE_TPM2
5997 _cleanup_closedir_ DIR *d = NULL;
5998 int r;
5999
6000 r = dlopen_tpm2();
6001 if (r < 0)
6002 return log_debug_errno(r, "TPM2 support is not installed.");
6003
6004 d = opendir("/sys/class/tpmrm");
6005 if (!d) {
6006 log_debug_errno(errno, "Failed to open /sys/class/tpmrm: %m");
6007 if (errno != ENOENT)
6008 return -errno;
6009 } else {
6010 _cleanup_free_ char *node = NULL;
6011
6012 for (;;) {
6013 struct dirent *de;
6014
6015 de = readdir_no_dot(d);
6016 if (!de)
6017 break;
6018
6019 if (node)
6020 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
6021 "More than one TPM2 (tpmrm) device found.");
6022
6023 node = path_join("/dev", de->d_name);
6024 if (!node)
6025 return log_oom_debug();
6026 }
6027
6028 if (node) {
6029 *ret = TAKE_PTR(node);
6030 return 0;
6031 }
6032 }
6033
6034 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
6035 #else
6036 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
6037 "TPM2 not supported on this build.");
6038 #endif
6039 }
6040
6041 #if HAVE_TPM2
6042 static const char* tpm2_userspace_event_type_table[_TPM2_USERSPACE_EVENT_TYPE_MAX] = {
6043 [TPM2_EVENT_PHASE] = "phase",
6044 [TPM2_EVENT_FILESYSTEM] = "filesystem",
6045 [TPM2_EVENT_VOLUME_KEY] = "volume-key",
6046 [TPM2_EVENT_MACHINE_ID] = "machine-id",
6047 };
6048
6049 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
6050
6051 const char *tpm2_userspace_log_path(void) {
6052 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
6053 }
6054
6055 const char *tpm2_firmware_log_path(void) {
6056 return secure_getenv("SYSTEMD_MEASURE_LOG_FIRMWARE") ?: "/sys/kernel/security/tpm0/binary_bios_measurements";
6057 }
6058
6059 #if HAVE_OPENSSL
6060 static int tpm2_userspace_log_open(void) {
6061 _cleanup_close_ int fd = -EBADF;
6062 struct stat st;
6063 const char *e;
6064 int r;
6065
6066 e = tpm2_userspace_log_path();
6067 (void) mkdir_parents(e, 0755);
6068
6069 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
6070 * because we use BSD file locking on it, and if anyone but root can access the file they can also
6071 * lock it, which we want to avoid. */
6072 fd = open(e, O_CREAT|O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
6073 if (fd < 0)
6074 return log_debug_errno(errno, "Failed to open TPM log file '%s' for writing, ignoring: %m", e);
6075
6076 if (flock(fd, LOCK_EX) < 0)
6077 return log_debug_errno(errno, "Failed to lock TPM log file '%s', ignoring: %m", e);
6078
6079 if (fstat(fd, &st) < 0)
6080 return log_debug_errno(errno, "Failed to fstat TPM log file '%s', ignoring: %m", e);
6081
6082 r = stat_verify_regular(&st);
6083 if (r < 0)
6084 return log_debug_errno(r, "TPM log file '%s' is not regular, ignoring: %m", e);
6085
6086 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
6087 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
6088 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
6089 * our assumed backend fs) doesn't know user xattrs. */
6090 if (st.st_mode & S_ISVTX)
6091 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "TPM log file '%s' aborted, ignoring.", e);
6092
6093 if (fchmod(fd, 0600 | S_ISVTX) < 0)
6094 return log_debug_errno(errno, "Failed to chmod() TPM log file '%s', ignoring: %m", e);
6095
6096 return TAKE_FD(fd);
6097 }
6098
6099 static int tpm2_userspace_log(
6100 int fd,
6101 unsigned pcr_index,
6102 const TPML_DIGEST_VALUES *values,
6103 Tpm2UserspaceEventType event_type,
6104 const char *description) {
6105
6106 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *array = NULL;
6107 _cleanup_free_ char *f = NULL;
6108 sd_id128_t boot_id;
6109 int r;
6110
6111 assert(values);
6112 assert(values->count > 0);
6113
6114 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
6115 * Format – the JSON flavour –
6116 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
6117 * ways from it, specifically:
6118 *
6119 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
6120 * through the whole logs (include firmware logs) before knowing what the next value is we should
6121 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
6122 * it in when it uses the data.
6123 *
6124 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
6125 * JSON array would mean that for each appending we'd have to read the whole log file fully into
6126 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
6127 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
6128 *
6129 * It should be possible to convert this format in a relatively straight-forward way into the
6130 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
6131 * determined from the full dataset.
6132 *
6133 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
6134 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
6135 * timestamp which can be used to order this measurement against possibly other measurements
6136 * independently done by other subsystems on the system.
6137 */
6138
6139 if (fd < 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
6140 return 0;
6141
6142 for (size_t i = 0; i < values->count; i++) {
6143 const EVP_MD *implementation;
6144 const char *a;
6145
6146 assert_se(a = tpm2_hash_alg_to_string(values->digests[i].hashAlg));
6147 assert_se(implementation = EVP_get_digestbyname(a));
6148
6149 r = json_variant_append_arrayb(
6150 &array, JSON_BUILD_OBJECT(
6151 JSON_BUILD_PAIR_STRING("hashAlg", a),
6152 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values->digests[i].digest, EVP_MD_size(implementation)))));
6153 if (r < 0)
6154 return log_debug_errno(r, "Failed to append digest object to JSON array: %m");
6155 }
6156
6157 assert(array);
6158
6159 r = sd_id128_get_boot(&boot_id);
6160 if (r < 0)
6161 return log_debug_errno(r, "Failed to acquire boot ID: %m");
6162
6163 r = json_build(&v, JSON_BUILD_OBJECT(
6164 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index)),
6165 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array)),
6166 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
6167 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
6168 JSON_BUILD_PAIR_CONDITION(description, "string", JSON_BUILD_STRING(description)),
6169 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id)),
6170 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME))),
6171 JSON_BUILD_PAIR_CONDITION(event_type >= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type)))))));
6172 if (r < 0)
6173 return log_debug_errno(r, "Failed to build log record JSON: %m");
6174
6175 r = json_variant_format(v, JSON_FORMAT_SEQ, &f);
6176 if (r < 0)
6177 return log_debug_errno(r, "Failed to format JSON: %m");
6178
6179 if (lseek(fd, 0, SEEK_END) < 0)
6180 return log_debug_errno(errno, "Failed to seek to end of JSON log: %m");
6181
6182 r = loop_write(fd, f, SIZE_MAX);
6183 if (r < 0)
6184 return log_debug_errno(r, "Failed to write JSON data to log: %m");
6185
6186 if (fsync(fd) < 0)
6187 return log_debug_errno(errno, "Failed to sync JSON data: %m");
6188
6189 /* Unset S_ISVTX again */
6190 if (fchmod(fd, 0600) < 0)
6191 return log_debug_errno(errno, "Failed to chmod() TPM log file, ignoring: %m");
6192
6193 r = fsync_full(fd);
6194 if (r < 0)
6195 return log_debug_errno(r, "Failed to sync JSON log: %m");
6196
6197 return 1;
6198 }
6199 #endif
6200
6201 int tpm2_extend_bytes(
6202 Tpm2Context *c,
6203 char **banks,
6204 unsigned pcr_index,
6205 const void *data,
6206 size_t data_size,
6207 const void *secret,
6208 size_t secret_size,
6209 Tpm2UserspaceEventType event_type,
6210 const char *description) {
6211
6212 #if HAVE_OPENSSL
6213 _cleanup_close_ int log_fd = -EBADF;
6214 TPML_DIGEST_VALUES values = {};
6215 TSS2_RC rc;
6216
6217 assert(c);
6218 assert(data || data_size == 0);
6219 assert(secret || secret_size == 0);
6220
6221 if (data_size == SIZE_MAX)
6222 data_size = strlen(data);
6223 if (secret_size == SIZE_MAX)
6224 secret_size = strlen(secret);
6225
6226 if (pcr_index >= TPM2_PCRS_MAX)
6227 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
6228
6229 if (strv_isempty(banks))
6230 return 0;
6231
6232 STRV_FOREACH(bank, banks) {
6233 const EVP_MD *implementation;
6234 int id;
6235
6236 assert_se(implementation = EVP_get_digestbyname(*bank));
6237
6238 if (values.count >= ELEMENTSOF(values.digests))
6239 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
6240
6241 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
6242 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
6243
6244 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
6245 if (id < 0)
6246 return log_debug_errno(id, "Can't map hash name to TPM2.");
6247
6248 values.digests[values.count].hashAlg = id;
6249
6250 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
6251 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
6252 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
6253 * secret for other purposes, maybe because it needs a shorter secret derived from it for
6254 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
6255 * private non-secret string instead. */
6256 if (secret_size > 0) {
6257 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
6258 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
6259 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
6260 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
6261
6262 values.count++;
6263 }
6264
6265 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
6266 * and our measurement and change either */
6267 log_fd = tpm2_userspace_log_open();
6268
6269 rc = sym_Esys_PCR_Extend(
6270 c->esys_context,
6271 ESYS_TR_PCR0 + pcr_index,
6272 ESYS_TR_PASSWORD,
6273 ESYS_TR_NONE,
6274 ESYS_TR_NONE,
6275 &values);
6276 if (rc != TSS2_RC_SUCCESS)
6277 return log_debug_errno(
6278 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
6279 "Failed to measure into PCR %u: %s",
6280 pcr_index,
6281 sym_Tss2_RC_Decode(rc));
6282
6283 /* Now, write what we just extended to the log, too. */
6284 (void) tpm2_userspace_log(log_fd, pcr_index, &values, event_type, description);
6285
6286 return 0;
6287 #else /* HAVE_OPENSSL */
6288 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
6289 #endif
6290 }
6291
6292 const uint16_t tpm2_hash_algorithms[] = {
6293 TPM2_ALG_SHA1,
6294 TPM2_ALG_SHA256,
6295 TPM2_ALG_SHA384,
6296 TPM2_ALG_SHA512,
6297 0,
6298 };
6299
6300 assert_cc(ELEMENTSOF(tpm2_hash_algorithms) == TPM2_N_HASH_ALGORITHMS + 1);
6301
6302 static size_t tpm2_hash_algorithm_index(uint16_t algorithm) {
6303 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++)
6304 if (tpm2_hash_algorithms[i] == algorithm)
6305 return i;
6306
6307 return SIZE_MAX;
6308 }
6309
6310 TPM2B_DIGEST *tpm2_pcr_prediction_result_get_hash(Tpm2PCRPredictionResult *result, uint16_t alg) {
6311 size_t alg_idx;
6312
6313 assert(result);
6314
6315 alg_idx = tpm2_hash_algorithm_index(alg);
6316 if (alg_idx == SIZE_MAX) /* Algorithm not known? */
6317 return NULL;
6318
6319 if (result->hash[alg_idx].size <= 0) /* No hash value for this algorithm? */
6320 return NULL;
6321
6322 return result->hash + alg_idx;
6323 }
6324
6325 void tpm2_pcr_prediction_done(Tpm2PCRPrediction *p) {
6326 assert(p);
6327
6328 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++)
6329 ordered_set_free(p->results[pcr]);
6330 }
6331
6332 static void tpm2_pcr_prediction_result_hash_func(const Tpm2PCRPredictionResult *banks, struct siphash *state) {
6333 assert(banks);
6334
6335 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++)
6336 siphash24_compress_safe(banks->hash[i].buffer, banks->hash[i].size, state);
6337 }
6338
6339 static int tpm2_pcr_prediction_result_compare_func(const Tpm2PCRPredictionResult *a, const Tpm2PCRPredictionResult *b) {
6340 int r;
6341
6342 assert(a);
6343 assert(b);
6344
6345 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++) {
6346 r = memcmp_nn(a->hash[i].buffer, a->hash[i].size,
6347 b->hash[i].buffer, b->hash[i].size);
6348 if (r != 0)
6349 return r;
6350 }
6351
6352 return 0;
6353 }
6354
6355 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
6356 tpm2_pcr_prediction_result_hash_ops,
6357 Tpm2PCRPredictionResult,
6358 tpm2_pcr_prediction_result_hash_func,
6359 tpm2_pcr_prediction_result_compare_func,
6360 Tpm2PCRPredictionResult,
6361 free);
6362
6363 static Tpm2PCRPredictionResult *find_prediction_result_by_algorithm(OrderedSet *set, Tpm2PCRPredictionResult *result, size_t alg_idx) {
6364 Tpm2PCRPredictionResult *f;
6365
6366 assert(result);
6367 assert(alg_idx != SIZE_MAX);
6368
6369 f = ordered_set_get(set, result); /* Full match? */
6370 if (f)
6371 return f;
6372
6373 /* If this doesn't match full, then see if there an entry that at least matches by the relevant
6374 * algorithm (we are fine if predictions are "incomplete" in some algorithms) */
6375
6376 ORDERED_SET_FOREACH(f, set)
6377 if (memcmp_nn(result->hash[alg_idx].buffer, result->hash[alg_idx].size,
6378 f->hash[alg_idx].buffer, f->hash[alg_idx].size) == 0)
6379 return f;
6380
6381 return NULL;
6382 }
6383
6384 bool tpm2_pcr_prediction_equal(
6385 Tpm2PCRPrediction *a,
6386 Tpm2PCRPrediction *b,
6387 uint16_t algorithm) {
6388
6389 if (a == b)
6390 return true;
6391 if (!a || !b)
6392 return false;
6393
6394 if (a->pcrs != b->pcrs)
6395 return false;
6396
6397 size_t alg_idx = tpm2_hash_algorithm_index(algorithm);
6398 if (alg_idx == SIZE_MAX)
6399 return false;
6400
6401 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6402 Tpm2PCRPredictionResult *banks;
6403
6404 ORDERED_SET_FOREACH(banks, a->results[pcr])
6405 if (!find_prediction_result_by_algorithm(b->results[pcr], banks, alg_idx))
6406 return false;
6407
6408 ORDERED_SET_FOREACH(banks, b->results[pcr])
6409 if (!find_prediction_result_by_algorithm(a->results[pcr], banks, alg_idx))
6410 return false;
6411 }
6412
6413 return true;
6414 }
6415
6416 int tpm2_pcr_prediction_to_json(
6417 const Tpm2PCRPrediction *prediction,
6418 uint16_t algorithm,
6419 JsonVariant **ret) {
6420
6421 _cleanup_(json_variant_unrefp) JsonVariant *aj = NULL;
6422 int r;
6423
6424 assert(prediction);
6425 assert(ret);
6426
6427 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6428 _cleanup_(json_variant_unrefp) JsonVariant *vj = NULL;
6429 Tpm2PCRPredictionResult *banks;
6430
6431 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6432 continue;
6433
6434 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6435
6436 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6437 if (!hash)
6438 continue;
6439
6440 r = json_variant_append_arrayb(
6441 &vj,
6442 JSON_BUILD_HEX(hash->buffer, hash->size));
6443 if (r < 0)
6444 return log_error_errno(r, "Failed to append hash variant to JSON array: %m");
6445 }
6446
6447 if (!vj)
6448 continue;
6449
6450 r = json_variant_append_arrayb(
6451 &aj,
6452 JSON_BUILD_OBJECT(
6453 JSON_BUILD_PAIR_INTEGER("pcr", pcr),
6454 JSON_BUILD_PAIR_VARIANT("values", vj)));
6455 if (r < 0)
6456 return log_error_errno(r, "Failed to append PCR variants to JSON array: %m");
6457 }
6458
6459 if (!aj) {
6460 r = json_variant_new_array(&aj, NULL, 0);
6461 if (r < 0)
6462 return r;
6463 }
6464
6465 *ret = TAKE_PTR(aj);
6466 return 0;
6467 }
6468
6469 int tpm2_pcr_prediction_from_json(
6470 Tpm2PCRPrediction *prediction,
6471 uint16_t algorithm,
6472 JsonVariant *aj) {
6473
6474 int r;
6475
6476 assert(prediction);
6477
6478 size_t alg_index = tpm2_hash_algorithm_index(algorithm);
6479 assert(alg_index < TPM2_N_HASH_ALGORITHMS);
6480
6481 if (!json_variant_is_array(aj))
6482 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR variant array is not an array.");
6483
6484 JsonVariant *pcr;
6485 JSON_VARIANT_ARRAY_FOREACH(pcr, aj) {
6486 JsonVariant *nr, *values;
6487
6488 nr = json_variant_by_key(pcr, "pcr");
6489 if (!nr)
6490 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry lacks PCR index field");
6491
6492 if (!json_variant_is_unsigned(nr) ||
6493 json_variant_unsigned(nr) >= TPM2_PCRS_MAX)
6494 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry PCR index is not an integer in the range 0…23");
6495
6496 values = json_variant_by_key(pcr, "values");
6497 if (!values)
6498 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry lacks values field");
6499
6500 if (!json_variant_is_array(values))
6501 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry values field is not an array");
6502
6503 prediction->pcrs |= UINT32_C(1) << json_variant_unsigned(nr);
6504
6505 JsonVariant *v;
6506 JSON_VARIANT_ARRAY_FOREACH(v, values) {
6507 _cleanup_free_ void *buffer = NULL;
6508 size_t size;
6509
6510 r = json_variant_unhex(v, &buffer, &size);
6511 if (r < 0)
6512 return log_error_errno(r, "Failed to decode PCR policy array hash value");
6513
6514 if (size <= 0)
6515 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PCR policy array hash value is zero.");
6516
6517 if (size > sizeof_field(TPM2B_DIGEST, buffer))
6518 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PCR policy array hash value is too large.");
6519
6520 _cleanup_free_ Tpm2PCRPredictionResult *banks = new0(Tpm2PCRPredictionResult, 1);
6521 if (!banks)
6522 return log_oom();
6523
6524 memcpy(banks->hash[alg_index].buffer, buffer, size);
6525 banks->hash[alg_index].size = size;
6526
6527 r = ordered_set_ensure_put(prediction->results + json_variant_unsigned(nr), &tpm2_pcr_prediction_result_hash_ops, banks);
6528 if (r == -EEXIST) /* Let's allow duplicates */
6529 continue;
6530 if (r < 0)
6531 return log_error_errno(r, "Failed to insert result into set: %m");
6532
6533 TAKE_PTR(banks);
6534 }
6535 }
6536
6537 return 0;
6538 }
6539
6540 int tpm2_calculate_policy_super_pcr(
6541 Tpm2PCRPrediction *prediction,
6542 uint16_t algorithm,
6543 TPM2B_DIGEST *pcr_policy) {
6544
6545 int r;
6546
6547 assert_se(prediction);
6548 assert_se(pcr_policy);
6549
6550 /* Start with a zero policy if not specified otherwise. */
6551 TPM2B_DIGEST super_pcr_policy_digest = *pcr_policy;
6552
6553 /* First we look for all PCRs that have exactly one allowed hash value, and generate a single PolicyPCR policy from them */
6554 _cleanup_free_ Tpm2PCRValue *single_values = NULL;
6555 size_t n_single_values = 0;
6556 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6557 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6558 continue;
6559
6560 if (ordered_set_size(prediction->results[pcr]) != 1)
6561 continue;
6562
6563 log_debug("Including PCR %" PRIu32 " in single value PolicyPCR expression", pcr);
6564
6565 Tpm2PCRPredictionResult *banks = ASSERT_PTR(ordered_set_first(prediction->results[pcr]));
6566
6567 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6568 if (!hash)
6569 continue;
6570
6571 if (!GREEDY_REALLOC(single_values, n_single_values + 1))
6572 return -ENOMEM;
6573
6574 single_values[n_single_values++] = TPM2_PCR_VALUE_MAKE(pcr, algorithm, *hash);
6575 }
6576
6577 if (n_single_values > 0) {
6578 /* Evolve policy based on the expected PCR value for what we found. */
6579 r = tpm2_calculate_policy_pcr(
6580 single_values,
6581 n_single_values,
6582 &super_pcr_policy_digest);
6583 if (r < 0)
6584 return r;
6585 }
6586
6587 /* Now deal with the PCRs for which we have variants, i.e. more than one allowed values */
6588 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6589 _cleanup_free_ TPM2B_DIGEST *pcr_policy_digest_variants = NULL;
6590 size_t n_pcr_policy_digest_variants = 0;
6591 Tpm2PCRPredictionResult *banks;
6592
6593 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6594 continue;
6595
6596 if (ordered_set_size(prediction->results[pcr]) <= 1) /* We only care for PCRs with 2 or more variants in this loop */
6597 continue;
6598
6599 if (ordered_set_size(prediction->results[pcr]) > 8)
6600 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "PCR policies with more than 8 alternatives per PCR are currently not supported.");
6601
6602 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6603 /* Start from the super PCR policy from the previous PCR we looked at so far. */
6604 TPM2B_DIGEST pcr_policy_digest = super_pcr_policy_digest;
6605
6606 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6607 if (!hash)
6608 continue;
6609
6610 /* Evolve it based on the expected PCR value for this PCR */
6611 r = tpm2_calculate_policy_pcr(
6612 &TPM2_PCR_VALUE_MAKE(
6613 pcr,
6614 algorithm,
6615 *hash),
6616 /* n_pcr_values= */ 1,
6617 &pcr_policy_digest);
6618 if (r < 0)
6619 return r;
6620
6621 /* Store away this new variant */
6622 if (!GREEDY_REALLOC(pcr_policy_digest_variants, n_pcr_policy_digest_variants + 1))
6623 return log_oom();
6624
6625 pcr_policy_digest_variants[n_pcr_policy_digest_variants++] = pcr_policy_digest;
6626
6627 log_debug("Calculated PCR policy variant %zu for PCR %" PRIu32, n_pcr_policy_digest_variants, pcr);
6628 }
6629
6630 assert_se(n_pcr_policy_digest_variants >= 2);
6631 assert_se(n_pcr_policy_digest_variants <= 8);
6632
6633 /* Now combine all our variant into one OR policy */
6634 r = tpm2_calculate_policy_or(
6635 pcr_policy_digest_variants,
6636 n_pcr_policy_digest_variants,
6637 &super_pcr_policy_digest);
6638 if (r < 0)
6639 return r;
6640
6641 log_debug("Combined %zu variants in OR policy.", n_pcr_policy_digest_variants);
6642 }
6643
6644 *pcr_policy = super_pcr_policy_digest;
6645 return 0;
6646 }
6647
6648 int tpm2_policy_super_pcr(
6649 Tpm2Context *c,
6650 const Tpm2Handle *session,
6651 const Tpm2PCRPrediction *prediction,
6652 uint16_t algorithm) {
6653
6654 int r;
6655
6656 assert_se(c);
6657 assert_se(session);
6658 assert_se(prediction);
6659
6660 TPM2B_DIGEST previous_policy_digest = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
6661
6662 uint32_t single_value_pcrs = 0;
6663
6664 /* Look for all PCRs that have only a singled allowed hash value, and synthesize a single PolicyPCR policy item for them */
6665 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6666 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6667 continue;
6668
6669 if (ordered_set_size(prediction->results[pcr]) != 1)
6670 continue;
6671
6672 log_debug("Including PCR %" PRIu32 " in single value PolicyPCR expression", pcr);
6673
6674 single_value_pcrs |= UINT32_C(1) << pcr;
6675 }
6676
6677 if (single_value_pcrs != 0) {
6678 TPML_PCR_SELECTION pcr_selection;
6679 tpm2_tpml_pcr_selection_from_mask(single_value_pcrs, algorithm, &pcr_selection);
6680
6681 _cleanup_free_ TPM2B_DIGEST *current_policy_digest = NULL;
6682 r = tpm2_policy_pcr(
6683 c,
6684 session,
6685 &pcr_selection,
6686 &current_policy_digest);
6687 if (r < 0)
6688 return r;
6689
6690 previous_policy_digest = *current_policy_digest;
6691 }
6692
6693 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6694 size_t n_branches;
6695
6696 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6697 continue;
6698
6699 n_branches = ordered_set_size(prediction->results[pcr]);
6700 if (n_branches < 1 || n_branches > 8)
6701 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Number of variants per PCR not in range 1…8");
6702
6703 if (n_branches == 1) /* Single choice PCRs are already covered by the loop above */
6704 continue;
6705
6706 log_debug("Submitting PCR/OR policy for PCR %" PRIu32, pcr);
6707
6708 TPML_PCR_SELECTION pcr_selection;
6709 tpm2_tpml_pcr_selection_from_mask(UINT32_C(1) << pcr, algorithm, &pcr_selection);
6710
6711 _cleanup_free_ TPM2B_DIGEST *current_policy_digest = NULL;
6712 r = tpm2_policy_pcr(
6713 c,
6714 session,
6715 &pcr_selection,
6716 &current_policy_digest);
6717 if (r < 0)
6718 return r;
6719
6720 _cleanup_free_ TPM2B_DIGEST *branches = NULL;
6721 branches = new0(TPM2B_DIGEST, n_branches);
6722 if (!branches)
6723 return log_oom();
6724
6725 Tpm2PCRPredictionResult *banks;
6726 size_t i = 0;
6727 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6728 TPM2B_DIGEST pcr_policy_digest = previous_policy_digest;
6729
6730 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6731 if (!hash)
6732 continue;
6733
6734 /* Evolve it based on the expected PCR value for this PCR */
6735 r = tpm2_calculate_policy_pcr(
6736 &TPM2_PCR_VALUE_MAKE(
6737 pcr,
6738 algorithm,
6739 *hash),
6740 /* n_pcr_values= */ 1,
6741 &pcr_policy_digest);
6742 if (r < 0)
6743 return r;
6744
6745 branches[i++] = pcr_policy_digest;
6746 }
6747
6748 assert_se(i == n_branches);
6749
6750 current_policy_digest = mfree(current_policy_digest);
6751 r = tpm2_policy_or(
6752 c,
6753 session,
6754 branches,
6755 n_branches,
6756 &current_policy_digest);
6757 if (r < 0)
6758 return r;
6759
6760 previous_policy_digest = *current_policy_digest;
6761 }
6762
6763 return 0;
6764 }
6765
6766 void tpm2_pcrlock_policy_done(Tpm2PCRLockPolicy *data) {
6767 assert(data);
6768
6769 data->prediction_json = json_variant_unref(data->prediction_json);
6770 tpm2_pcr_prediction_done(&data->prediction);
6771 iovec_done(&data->nv_handle);
6772 iovec_done(&data->nv_public);
6773 iovec_done(&data->srk_handle);
6774 iovec_done(&data->pin_public);
6775 iovec_done(&data->pin_private);
6776 }
6777
6778 static int json_dispatch_tpm2_algorithm(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
6779 uint16_t *algorithm = ASSERT_PTR(userdata);
6780 int r;
6781
6782 r = tpm2_hash_alg_from_string(json_variant_string(variant));
6783 if (r < 0 || tpm2_hash_algorithm_index(r) == SIZE_MAX)
6784 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid hash algorithm: %s", json_variant_string(variant));
6785
6786 *algorithm = r;
6787 return 0;
6788 }
6789
6790 int tpm2_pcrlock_search_file(const char *path, FILE **ret_file, char **ret_path) {
6791 static const char search[] =
6792 "/run/systemd\0"
6793 "/var/lib/systemd\0";
6794
6795 int r;
6796
6797 if (!path)
6798 path = "pcrlock.json";
6799
6800 r = search_and_fopen_nulstr(path, ret_file ? "re" : NULL, NULL, search, ret_file, ret_path);
6801 if (r < 0)
6802 return log_debug_errno(r, "Failed to find TPM2 pcrlock policy file '%s': %m", path);
6803
6804 return 0;
6805 }
6806
6807 int tpm2_pcrlock_policy_from_json(
6808 JsonVariant *v,
6809 Tpm2PCRLockPolicy *ret_policy) {
6810
6811 /* We use a type check of _JSON_VARIANT_TYPE_INVALID for the integer fields to allow
6812 * json_dispatch_uint32() to parse strings as integers to work around the integer type weakness of
6813 * JSON's design. */
6814 JsonDispatch policy_dispatch[] = {
6815 { "pcrBank", JSON_VARIANT_STRING, json_dispatch_tpm2_algorithm, offsetof(Tpm2PCRLockPolicy, algorithm), JSON_MANDATORY },
6816 { "pcrValues", JSON_VARIANT_ARRAY, json_dispatch_variant, offsetof(Tpm2PCRLockPolicy, prediction_json), JSON_MANDATORY },
6817 { "nvIndex", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint32, offsetof(Tpm2PCRLockPolicy, nv_index), JSON_MANDATORY },
6818 { "nvHandle", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, nv_handle), JSON_MANDATORY },
6819 { "nvPublic", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, nv_public), JSON_MANDATORY },
6820 { "srkHandle", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, srk_handle), JSON_MANDATORY },
6821 { "pinPublic", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, pin_public), JSON_MANDATORY },
6822 { "pinPrivate", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, pin_private), JSON_MANDATORY },
6823 {}
6824 };
6825
6826 _cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy policy = {};
6827 int r;
6828
6829 assert(v);
6830 assert(ret_policy);
6831
6832 r = json_dispatch(v, policy_dispatch, JSON_LOG, &policy);
6833 if (r < 0)
6834 return r;
6835
6836 r = tpm2_pcr_prediction_from_json(&policy.prediction, policy.algorithm, policy.prediction_json);
6837 if (r < 0)
6838 return r;
6839
6840 *ret_policy = TAKE_STRUCT(policy);
6841 return 1;
6842 }
6843
6844 int tpm2_pcrlock_policy_load(
6845 const char *path,
6846 Tpm2PCRLockPolicy *ret_policy) {
6847
6848 _cleanup_free_ char *discovered_path = NULL;
6849 _cleanup_fclose_ FILE *f = NULL;
6850 int r;
6851
6852 r = tpm2_pcrlock_search_file(path, &f, &discovered_path);
6853 if (r == -ENOENT) {
6854 *ret_policy = (Tpm2PCRLockPolicy) {};
6855 return 0;
6856 }
6857 if (r < 0)
6858 return log_error_errno(r, "Failed to load TPM2 pcrlock policy file: %m");
6859
6860 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
6861 r = json_parse_file(
6862 f,
6863 discovered_path,
6864 /* flags = */ 0,
6865 &v,
6866 /* ret_line= */ NULL,
6867 /* ret_column= */ NULL);
6868 if (r < 0)
6869 return log_error_errno(r, "Failed to parse existing pcrlock policy file '%s': %m", discovered_path);
6870
6871 return tpm2_pcrlock_policy_from_json(v, ret_policy);
6872 }
6873
6874 static int pcrlock_policy_load_credential(
6875 const char *name,
6876 const struct iovec *data,
6877 Tpm2PCRLockPolicy *ret) {
6878
6879 _cleanup_free_ char *c = NULL;
6880 int r;
6881
6882 assert(name);
6883
6884 c = strdup(name);
6885 if (!c)
6886 return log_oom();
6887
6888 ascii_strlower(c); /* Lowercase, to match what we did at encryption time */
6889
6890 _cleanup_(iovec_done) struct iovec decoded = {};
6891 r = decrypt_credential_and_warn(
6892 c,
6893 now(CLOCK_REALTIME),
6894 /* tpm2_device= */ NULL,
6895 /* tpm2_signature_path= */ NULL,
6896 UID_INVALID,
6897 data,
6898 CREDENTIAL_ALLOW_NULL,
6899 &decoded);
6900 if (r < 0)
6901 return r;
6902
6903 if (memchr(decoded.iov_base, 0, decoded.iov_len))
6904 return log_error_errno(r, "Credential '%s' contains embedded NUL byte, refusing.", name);
6905
6906 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
6907 r = json_parse(decoded.iov_base,
6908 /* flags= */ 0,
6909 &v,
6910 /* ret_line= */ NULL,
6911 /* ret_column= */ NULL);
6912 if (r < 0)
6913 return log_error_errno(r, "Failed to parse pcrlock policy: %m");
6914
6915 r = tpm2_pcrlock_policy_from_json(v, ret);
6916 if (r < 0)
6917 return r;
6918
6919 return 0;
6920 }
6921
6922 int tpm2_pcrlock_policy_from_credentials(
6923 const struct iovec *srk,
6924 const struct iovec *nv,
6925 Tpm2PCRLockPolicy *ret) {
6926
6927 _cleanup_close_ int dfd = -EBADF;
6928 int r;
6929
6930 /* During boot we'll not have access to the pcrlock.json file in /var/. In order to support
6931 * pcrlock-bound root file systems we'll store a copy of the JSON data, wrapped in an (plaintext)
6932 * credential in the ESP or XBOOTLDR partition. There might be multiple of those however (because of
6933 * multi-boot), hence we use the SRK and NV data from the LUKS2 header as search key, and parse all
6934 * such JSON policies until we find a matching one. */
6935
6936 const char *cp = secure_getenv("SYSTEMD_ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY") ?: ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY;
6937
6938 dfd = open(cp, O_CLOEXEC|O_DIRECTORY);
6939 if (dfd < 0) {
6940 if (errno == ENOENT) {
6941 log_debug("No encrypted system credentials passed.");
6942 return 0;
6943 }
6944
6945 return log_error_errno(errno, "Failed to open system credentials directory.");
6946 }
6947
6948 _cleanup_free_ DirectoryEntries *de = NULL;
6949 r = readdir_all(dfd, RECURSE_DIR_IGNORE_DOT, &de);
6950 if (r < 0)
6951 return log_error_errno(r, "Failed to enumerate system credentials: %m");
6952
6953 FOREACH_ARRAY(i, de->entries, de->n_entries) {
6954 _cleanup_(iovec_done) struct iovec data = {};
6955 struct dirent *d = *i;
6956
6957 if (!startswith_no_case(d->d_name, "pcrlock.")) /* VFAT is case-insensitive, hence don't be too strict here */
6958 continue;
6959
6960 r = read_full_file_full(
6961 dfd, d->d_name,
6962 /* offset= */ UINT64_MAX,
6963 /* size= */ CREDENTIAL_ENCRYPTED_SIZE_MAX,
6964 READ_FULL_FILE_UNBASE64|READ_FULL_FILE_FAIL_WHEN_LARGER,
6965 /* bind_name= */ NULL,
6966 (char**) &data.iov_base,
6967 &data.iov_len);
6968 if (r == -ENOENT)
6969 continue;
6970 if (r < 0) {
6971 log_warning_errno(r, "Failed to read credentials file %s/%s, skipping: %m", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY, d->d_name);
6972 continue;
6973 }
6974
6975 _cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy loaded_policy = {};
6976 r = pcrlock_policy_load_credential(
6977 d->d_name,
6978 &data,
6979 &loaded_policy);
6980 if (r < 0) {
6981 log_warning_errno(r, "Loading of pcrlock policy from credential '%s/%s' failed, skipping.", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY, d->d_name);
6982 continue;
6983 }
6984
6985 if ((!srk || iovec_memcmp(srk, &loaded_policy.srk_handle) == 0) &&
6986 (!nv || iovec_memcmp(nv, &loaded_policy.nv_handle) == 0)) {
6987 *ret = TAKE_STRUCT(loaded_policy);
6988 return 1;
6989 }
6990 }
6991
6992 log_info("No pcrlock policy found among system credentials.");
6993 *ret = (Tpm2PCRLockPolicy) {};
6994 return 0;
6995 }
6996
6997 int tpm2_load_public_key_file(const char *path, TPM2B_PUBLIC *ret) {
6998 _cleanup_free_ char *device_key_buffer = NULL;
6999 TPM2B_PUBLIC device_key_public = {};
7000 size_t device_key_buffer_size;
7001 TSS2_RC rc;
7002 int r;
7003
7004 assert(path);
7005 assert(ret);
7006
7007 r = dlopen_tpm2();
7008 if (r < 0)
7009 return log_debug_errno(r, "TPM2 support not installed: %m");
7010
7011 r = read_full_file(path, &device_key_buffer, &device_key_buffer_size);
7012 if (r < 0)
7013 return log_error_errno(r, "Failed to read device key from file '%s': %m", path);
7014
7015 size_t offset = 0;
7016 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(
7017 (uint8_t*) device_key_buffer,
7018 device_key_buffer_size,
7019 &offset,
7020 &device_key_public);
7021 if (rc != TSS2_RC_SUCCESS)
7022 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7023 "Could not unmarshal public key from file.");
7024
7025 assert(offset <= device_key_buffer_size);
7026 if (offset != device_key_buffer_size)
7027 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7028 "Found %zu bytes of trailing garbage in public key file.",
7029 device_key_buffer_size - offset);
7030
7031 *ret = device_key_public;
7032 return 0;
7033 }
7034 #endif
7035
7036 char *tpm2_pcr_mask_to_string(uint32_t mask) {
7037 _cleanup_free_ char *s = NULL;
7038
7039 FOREACH_PCR_IN_MASK(n, mask)
7040 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
7041 return NULL;
7042
7043 if (!s)
7044 return strdup("");
7045
7046 return TAKE_PTR(s);
7047 }
7048
7049 int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
7050 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
7051 int r;
7052
7053 assert(ret);
7054
7055 for (size_t i = 0; i < TPM2_PCRS_MAX; i++) {
7056 _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
7057
7058 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
7059 continue;
7060
7061 r = json_variant_new_integer(&e, i);
7062 if (r < 0)
7063 return r;
7064
7065 r = json_variant_append_array(&a, e);
7066 if (r < 0)
7067 return r;
7068 }
7069
7070 if (!a)
7071 return json_variant_new_array(ret, NULL, 0);
7072
7073 *ret = TAKE_PTR(a);
7074 return 0;
7075 }
7076
7077 int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
7078 JsonVariant *e;
7079 uint32_t mask = 0;
7080
7081 if (!json_variant_is_array(v))
7082 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
7083
7084 JSON_VARIANT_ARRAY_FOREACH(e, v) {
7085 uint64_t u;
7086
7087 if (!json_variant_is_unsigned(e))
7088 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
7089
7090 u = json_variant_unsigned(e);
7091 if (u >= TPM2_PCRS_MAX)
7092 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
7093
7094 mask |= UINT32_C(1) << u;
7095 }
7096
7097 if (ret)
7098 *ret = mask;
7099
7100 return 0;
7101 }
7102
7103 int tpm2_make_luks2_json(
7104 int keyslot,
7105 uint32_t hash_pcr_mask,
7106 uint16_t pcr_bank,
7107 const struct iovec *pubkey,
7108 uint32_t pubkey_pcr_mask,
7109 uint16_t primary_alg,
7110 const struct iovec *blob,
7111 const struct iovec *policy_hash,
7112 const struct iovec *salt,
7113 const struct iovec *srk,
7114 const struct iovec *pcrlock_nv,
7115 TPM2Flags flags,
7116 JsonVariant **ret) {
7117
7118 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
7119 _cleanup_free_ char *keyslot_as_string = NULL;
7120 int r;
7121
7122 assert(iovec_is_valid(pubkey));
7123 assert(iovec_is_valid(blob));
7124 assert(iovec_is_valid(policy_hash));
7125
7126 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
7127 return -ENOMEM;
7128
7129 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
7130 if (r < 0)
7131 return r;
7132
7133 if (pubkey_pcr_mask != 0) {
7134 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
7135 if (r < 0)
7136 return r;
7137 }
7138
7139 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
7140 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
7141 * object should use "_" rather than "-" in field names. */
7142
7143 r = json_build(&v,
7144 JSON_BUILD_OBJECT(
7145 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
7146 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
7147 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_IOVEC_BASE64(blob)),
7148 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7149 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
7150 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg))),
7151 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_IOVEC_HEX(policy_hash)),
7152 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
7153 JSON_BUILD_PAIR("tpm2_pcrlock", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PCRLOCK)),
7154 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
7155 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_IOVEC_BASE64(pubkey)),
7156 JSON_BUILD_PAIR_CONDITION(iovec_is_set(salt), "tpm2_salt", JSON_BUILD_IOVEC_BASE64(salt)),
7157 JSON_BUILD_PAIR_CONDITION(iovec_is_set(srk), "tpm2_srk", JSON_BUILD_IOVEC_BASE64(srk)),
7158 JSON_BUILD_PAIR_CONDITION(iovec_is_set(pcrlock_nv), "tpm2_pcrlock_nv", JSON_BUILD_IOVEC_BASE64(pcrlock_nv))));
7159 if (r < 0)
7160 return r;
7161
7162 if (ret)
7163 *ret = TAKE_PTR(v);
7164
7165 return keyslot;
7166 }
7167
7168 int tpm2_parse_luks2_json(
7169 JsonVariant *v,
7170 int *ret_keyslot,
7171 uint32_t *ret_hash_pcr_mask,
7172 uint16_t *ret_pcr_bank,
7173 struct iovec *ret_pubkey,
7174 uint32_t *ret_pubkey_pcr_mask,
7175 uint16_t *ret_primary_alg,
7176 struct iovec *ret_blob,
7177 struct iovec *ret_policy_hash,
7178 struct iovec *ret_salt,
7179 struct iovec *ret_srk,
7180 struct iovec *ret_pcrlock_nv,
7181 TPM2Flags *ret_flags) {
7182
7183 _cleanup_(iovec_done) struct iovec blob = {}, policy_hash = {}, pubkey = {}, salt = {}, srk = {}, pcrlock_nv = {};
7184 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
7185 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
7186 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
7187 int r, keyslot = -1;
7188 TPM2Flags flags = 0;
7189 JsonVariant *w;
7190
7191 assert(v);
7192
7193 if (ret_keyslot) {
7194 keyslot = cryptsetup_get_keyslot_from_token(v);
7195 if (keyslot < 0) {
7196 /* Return a recognizable error when parsing this field, so that callers can handle parsing
7197 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
7198 * spec */
7199 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
7200 return -EUCLEAN;
7201 }
7202 }
7203
7204 w = json_variant_by_key(v, "tpm2-pcrs");
7205 if (!w)
7206 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
7207
7208 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
7209 if (r < 0)
7210 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
7211
7212 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
7213 * to SHA256. */
7214 w = json_variant_by_key(v, "tpm2-pcr-bank");
7215 if (w) {
7216 /* The PCR bank field is optional */
7217
7218 if (!json_variant_is_string(w))
7219 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
7220
7221 r = tpm2_hash_alg_from_string(json_variant_string(w));
7222 if (r < 0)
7223 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
7224
7225 pcr_bank = r;
7226 }
7227
7228 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
7229 * the algorithm was hardcoded to ECC. */
7230 w = json_variant_by_key(v, "tpm2-primary-alg");
7231 if (w) {
7232 /* The primary key algorithm is optional */
7233
7234 if (!json_variant_is_string(w))
7235 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
7236
7237 r = tpm2_asym_alg_from_string(json_variant_string(w));
7238 if (r < 0)
7239 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
7240
7241 primary_alg = r;
7242 }
7243
7244 w = json_variant_by_key(v, "tpm2-blob");
7245 if (!w)
7246 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
7247
7248 r = json_variant_unbase64_iovec(w, &blob);
7249 if (r < 0)
7250 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
7251
7252 w = json_variant_by_key(v, "tpm2-policy-hash");
7253 if (!w)
7254 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
7255
7256 r = json_variant_unhex_iovec(w, &policy_hash);
7257 if (r < 0)
7258 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
7259
7260 w = json_variant_by_key(v, "tpm2-pin");
7261 if (w) {
7262 if (!json_variant_is_boolean(w))
7263 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
7264
7265 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
7266 }
7267
7268 w = json_variant_by_key(v, "tpm2_pcrlock");
7269 if (w) {
7270 if (!json_variant_is_boolean(w))
7271 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 pclock policy is not a boolean.");
7272
7273 SET_FLAG(flags, TPM2_FLAGS_USE_PCRLOCK, json_variant_boolean(w));
7274 }
7275
7276 w = json_variant_by_key(v, "tpm2_salt");
7277 if (w) {
7278 r = json_variant_unbase64_iovec(w, &salt);
7279 if (r < 0)
7280 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
7281 }
7282
7283 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
7284 if (w) {
7285 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
7286 if (r < 0)
7287 return r;
7288 }
7289
7290 w = json_variant_by_key(v, "tpm2_pubkey");
7291 if (w) {
7292 r = json_variant_unbase64_iovec(w, &pubkey);
7293 if (r < 0)
7294 return log_debug_errno(r, "Failed to decode PCR public key.");
7295 } else if (pubkey_pcr_mask != 0)
7296 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
7297
7298 w = json_variant_by_key(v, "tpm2_srk");
7299 if (w) {
7300 r = json_variant_unbase64_iovec(w, &srk);
7301 if (r < 0)
7302 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
7303 }
7304
7305 w = json_variant_by_key(v, "tpm2_pcrlock_nv");
7306 if (w) {
7307 r = json_variant_unbase64_iovec(w, &pcrlock_nv);
7308 if (r < 0)
7309 return log_debug_errno(r, "Invalid base64 data in 'tpm2_pcrlock_nv' field.");
7310 }
7311
7312 if (ret_keyslot)
7313 *ret_keyslot = keyslot;
7314 if (ret_hash_pcr_mask)
7315 *ret_hash_pcr_mask = hash_pcr_mask;
7316 if (ret_pcr_bank)
7317 *ret_pcr_bank = pcr_bank;
7318 if (ret_pubkey)
7319 *ret_pubkey = TAKE_STRUCT(pubkey);
7320 if (ret_pubkey_pcr_mask)
7321 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
7322 if (ret_primary_alg)
7323 *ret_primary_alg = primary_alg;
7324 if (ret_blob)
7325 *ret_blob = TAKE_STRUCT(blob);
7326 if (ret_policy_hash)
7327 *ret_policy_hash = TAKE_STRUCT(policy_hash);
7328 if (ret_salt)
7329 *ret_salt = TAKE_STRUCT(salt);
7330 if (ret_srk)
7331 *ret_srk = TAKE_STRUCT(srk);
7332 if (ret_pcrlock_nv)
7333 *ret_pcrlock_nv = TAKE_STRUCT(pcrlock_nv);
7334 if (ret_flags)
7335 *ret_flags = flags;
7336 return 0;
7337 }
7338
7339 int tpm2_hash_alg_to_size(uint16_t alg) {
7340 switch (alg) {
7341 case TPM2_ALG_SHA1:
7342 return 20;
7343 case TPM2_ALG_SHA256:
7344 return 32;
7345 case TPM2_ALG_SHA384:
7346 return 48;
7347 case TPM2_ALG_SHA512:
7348 return 64;
7349 default:
7350 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm id 0x%" PRIx16, alg);
7351 }
7352 }
7353
7354 const char *tpm2_hash_alg_to_string(uint16_t alg) {
7355 switch (alg) {
7356 case TPM2_ALG_SHA1:
7357 return "sha1";
7358 case TPM2_ALG_SHA256:
7359 return "sha256";
7360 case TPM2_ALG_SHA384:
7361 return "sha384";
7362 case TPM2_ALG_SHA512:
7363 return "sha512";
7364 default:
7365 log_debug("Unknown hash algorithm id 0x%" PRIx16, alg);
7366 return NULL;
7367 }
7368 }
7369
7370 int tpm2_hash_alg_from_string(const char *alg) {
7371 if (strcaseeq_ptr(alg, "sha1"))
7372 return TPM2_ALG_SHA1;
7373 if (strcaseeq_ptr(alg, "sha256"))
7374 return TPM2_ALG_SHA256;
7375 if (strcaseeq_ptr(alg, "sha384"))
7376 return TPM2_ALG_SHA384;
7377 if (strcaseeq_ptr(alg, "sha512"))
7378 return TPM2_ALG_SHA512;
7379 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm name '%s'", alg);
7380 }
7381
7382 const char *tpm2_asym_alg_to_string(uint16_t alg) {
7383 switch (alg) {
7384 case TPM2_ALG_ECC:
7385 return "ecc";
7386 case TPM2_ALG_RSA:
7387 return "rsa";
7388 default:
7389 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16, alg);
7390 return NULL;
7391 }
7392 }
7393
7394 int tpm2_asym_alg_from_string(const char *alg) {
7395 if (strcaseeq_ptr(alg, "ecc"))
7396 return TPM2_ALG_ECC;
7397 if (strcaseeq_ptr(alg, "rsa"))
7398 return TPM2_ALG_RSA;
7399 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown asymmetric algorithm name '%s'", alg);
7400 }
7401
7402 const char *tpm2_sym_alg_to_string(uint16_t alg) {
7403 switch (alg) {
7404 #if HAVE_TPM2
7405 case TPM2_ALG_AES:
7406 return "aes";
7407 #endif
7408 default:
7409 log_debug("Unknown symmetric algorithm id 0x%" PRIx16, alg);
7410 return NULL;
7411 }
7412 }
7413
7414 int tpm2_sym_alg_from_string(const char *alg) {
7415 #if HAVE_TPM2
7416 if (strcaseeq_ptr(alg, "aes"))
7417 return TPM2_ALG_AES;
7418 #endif
7419 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric algorithm name '%s'", alg);
7420 }
7421
7422 const char *tpm2_sym_mode_to_string(uint16_t mode) {
7423 switch (mode) {
7424 #if HAVE_TPM2
7425 case TPM2_ALG_CTR:
7426 return "ctr";
7427 case TPM2_ALG_OFB:
7428 return "ofb";
7429 case TPM2_ALG_CBC:
7430 return "cbc";
7431 case TPM2_ALG_CFB:
7432 return "cfb";
7433 case TPM2_ALG_ECB:
7434 return "ecb";
7435 #endif
7436 default:
7437 log_debug("Unknown symmetric mode id 0x%" PRIx16, mode);
7438 return NULL;
7439 }
7440 }
7441
7442 int tpm2_sym_mode_from_string(const char *mode) {
7443 #if HAVE_TPM2
7444 if (strcaseeq_ptr(mode, "ctr"))
7445 return TPM2_ALG_CTR;
7446 if (strcaseeq_ptr(mode, "ofb"))
7447 return TPM2_ALG_OFB;
7448 if (strcaseeq_ptr(mode, "cbc"))
7449 return TPM2_ALG_CBC;
7450 if (strcaseeq_ptr(mode, "cfb"))
7451 return TPM2_ALG_CFB;
7452 if (strcaseeq_ptr(mode, "ecb"))
7453 return TPM2_ALG_ECB;
7454 #endif
7455 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric mode name '%s'", mode);
7456 }
7457
7458 Tpm2Support tpm2_support(void) {
7459 Tpm2Support support = TPM2_SUPPORT_NONE;
7460 int r;
7461
7462 if (detect_container() <= 0) {
7463 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
7464 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
7465 * let's assume containers never have a TPM, at least for now. */
7466
7467 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
7468 if (r < 0) {
7469 if (r != -ENOENT)
7470 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
7471 } else if (r == 0) /* populated! */
7472 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
7473 else
7474 /* If the directory exists but is empty, we know the subsystem is enabled but no
7475 * driver has been loaded yet. */
7476 support |= TPM2_SUPPORT_SUBSYSTEM;
7477 }
7478
7479 if (efi_has_tpm2())
7480 support |= TPM2_SUPPORT_FIRMWARE;
7481
7482 #if HAVE_TPM2
7483 support |= TPM2_SUPPORT_SYSTEM;
7484
7485 r = dlopen_tpm2();
7486 if (r >= 0)
7487 support |= TPM2_SUPPORT_LIBRARIES;
7488 #endif
7489
7490 return support;
7491 }
7492
7493 #if HAVE_TPM2
7494 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
7495 TPMI_ALG_HASH default_hash = 0;
7496 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
7497 if (v->hash != 0) {
7498 default_hash = v->hash;
7499 break;
7500 }
7501
7502 if (default_hash != 0)
7503 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
7504 if (v->hash == 0)
7505 v->hash = default_hash;
7506 }
7507 #endif
7508
7509 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
7510 * parse_*_argument() functions. */
7511
7512 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
7513 *
7514 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
7515 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
7516 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
7517 *
7518 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
7519 * tpm2_parse_pcr_argument_append(). */
7520 int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
7521 #if HAVE_TPM2
7522 int r;
7523
7524 assert(arg);
7525 assert(ret_pcr_values);
7526 assert(ret_n_pcr_values);
7527
7528 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
7529 size_t n_pcr_values = 0;
7530 r = tpm2_pcr_values_from_string(arg, &pcr_values, &n_pcr_values);
7531 if (r < 0)
7532 return log_error_errno(r, "Could not parse PCR values from '%s': %m", arg);
7533
7534 tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
7535
7536 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
7537
7538 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
7539 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
7540
7541 *ret_pcr_values = TAKE_PTR(pcr_values);
7542 *ret_n_pcr_values = n_pcr_values;
7543
7544 return 0;
7545 #else
7546 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7547 #endif
7548 }
7549
7550 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
7551 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
7552 * must be correct.
7553 *
7554 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
7555 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
7556 * algorithm check applied again (in case either the previous or current array had no default hash
7557 * algorithm), and then the resulting array is sorted and rechecked for validity. */
7558 int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values) {
7559 #if HAVE_TPM2
7560 int r;
7561
7562 assert(arg);
7563 assert(pcr_values);
7564 assert(n_pcr_values);
7565
7566 _cleanup_free_ Tpm2PCRValue *more_pcr_values = NULL;
7567 size_t n_more_pcr_values;
7568 r = tpm2_parse_pcr_argument(arg, &more_pcr_values, &n_more_pcr_values);
7569 if (r < 0)
7570 return r;
7571
7572 /* If we got previous values, append them. */
7573 if (*pcr_values && !GREEDY_REALLOC_APPEND(more_pcr_values, n_more_pcr_values, *pcr_values, *n_pcr_values))
7574 return log_oom();
7575
7576 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values, n_more_pcr_values);
7577
7578 tpm2_sort_pcr_values(more_pcr_values, n_more_pcr_values);
7579
7580 if (!tpm2_pcr_values_valid(more_pcr_values, n_more_pcr_values))
7581 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
7582
7583 SWAP_TWO(*pcr_values, more_pcr_values);
7584 *n_pcr_values = n_more_pcr_values;
7585
7586 return 0;
7587 #else
7588 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7589 #endif
7590 }
7591
7592 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
7593 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
7594 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
7595 * UINT32_MAX, and or-ing the mask otherwise. */
7596 int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *ret_mask) {
7597 #if HAVE_TPM2
7598 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
7599 size_t n_pcr_values;
7600 int r;
7601
7602 assert(arg);
7603 assert(ret_mask);
7604
7605 r = tpm2_parse_pcr_argument(arg, &pcr_values, &n_pcr_values);
7606 if (r < 0)
7607 return r;
7608
7609 if (n_pcr_values == 0) {
7610 /* This retains the previous behavior of clearing the mask if the arg is empty */
7611 *ret_mask = 0;
7612 return 0;
7613 }
7614
7615 size_t hash_count;
7616 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
7617 if (r < 0)
7618 return log_error_errno(r, "Could not get hash count from pcr values: %m");
7619
7620 if (hash_count > 1)
7621 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR hash banks selected.");
7622
7623 uint32_t new_mask;
7624 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
7625 if (r < 0)
7626 return log_error_errno(r, "Could not get pcr values mask: %m");
7627
7628 if (*ret_mask == UINT32_MAX)
7629 *ret_mask = new_mask;
7630 else
7631 *ret_mask |= new_mask;
7632
7633 return 0;
7634 #else
7635 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7636 #endif
7637 }
7638
7639 int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
7640 _cleanup_strv_free_ char **search = NULL;
7641 _cleanup_free_ char *discovered_path = NULL;
7642 _cleanup_fclose_ FILE *f = NULL;
7643 int r;
7644
7645 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
7646 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7647
7648 search = strv_new(CONF_PATHS("systemd"));
7649 if (!search)
7650 return log_oom_debug();
7651
7652 if (!path) {
7653 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
7654 * this case include /.extra/ in the search path, but only in this case, and if we run in the
7655 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
7656
7657 path = "tpm2-pcr-signature.json";
7658
7659 if (in_initrd())
7660 if (strv_extend(&search, "/.extra") < 0)
7661 return log_oom_debug();
7662 }
7663
7664 r = search_and_fopen(path, "re", NULL, (const char**) search, &f, &discovered_path);
7665 if (r < 0)
7666 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
7667
7668 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
7669 if (r < 0)
7670 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
7671
7672 return 0;
7673 }
7674
7675 int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
7676 _cleanup_free_ char *discovered_path = NULL;
7677 _cleanup_fclose_ FILE *f = NULL;
7678 int r;
7679
7680 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
7681 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7682
7683 if (!path)
7684 path = "tpm2-pcr-public-key.pem";
7685
7686 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
7687 if (r < 0)
7688 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
7689
7690 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
7691 if (r < 0)
7692 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
7693
7694 return 0;
7695 }
7696
7697 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
7698
7699 /*
7700 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
7701 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
7702 * I found the wikipedia entry relevant and it contains links to
7703 * relevant RFCs:
7704 * - https://en.wikipedia.org/wiki/PBKDF2
7705 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
7706 */
7707 int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
7708 size_t passlen,
7709 const void *salt,
7710 size_t saltlen,
7711 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
7712
7713 _cleanup_(erase_and_freep) uint8_t *buffer = NULL;
7714 uint8_t u[SHA256_DIGEST_SIZE];
7715
7716 /* To keep this simple, since derived KeyLen (dkLen in docs)
7717 * Is the same as the hash output, we don't need multiple
7718 * blocks. Part of the algorithm is to add the block count
7719 * in, but this can be hardcoded to 1.
7720 */
7721 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
7722
7723 assert (salt);
7724 assert (saltlen > 0);
7725 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
7726 assert (passlen > 0);
7727
7728 /*
7729 * Build a buffer of salt + block_cnt and hmac_sha256 it we
7730 * do this as we don't have a context builder for HMAC_SHA256.
7731 */
7732 buffer = malloc(saltlen + sizeof(block_cnt));
7733 if (!buffer)
7734 return -ENOMEM;
7735
7736 memcpy(buffer, salt, saltlen);
7737 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
7738
7739 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
7740
7741 /* dk needs to be an unmodified u as u gets modified in the loop */
7742 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
7743 uint8_t *dk = ret_key;
7744
7745 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
7746 hmac_sha256(pass, passlen, u, sizeof(u), u);
7747
7748 for (size_t j=0; j < sizeof(u); j++)
7749 dk[j] ^= u[j];
7750 }
7751
7752 return 0;
7753 }
7754
7755 static const char* const tpm2_pcr_index_table[_TPM2_PCR_INDEX_MAX_DEFINED] = {
7756 [TPM2_PCR_PLATFORM_CODE] = "platform-code",
7757 [TPM2_PCR_PLATFORM_CONFIG] = "platform-config",
7758 [TPM2_PCR_EXTERNAL_CODE] = "external-code",
7759 [TPM2_PCR_EXTERNAL_CONFIG] = "external-config",
7760 [TPM2_PCR_BOOT_LOADER_CODE] = "boot-loader-code",
7761 [TPM2_PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
7762 [TPM2_PCR_HOST_PLATFORM] = "host-platform",
7763 [TPM2_PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
7764 [TPM2_PCR_KERNEL_INITRD] = "kernel-initrd",
7765 [TPM2_PCR_IMA] = "ima",
7766 [TPM2_PCR_KERNEL_BOOT] = "kernel-boot",
7767 [TPM2_PCR_KERNEL_CONFIG] = "kernel-config",
7768 [TPM2_PCR_SYSEXTS] = "sysexts",
7769 [TPM2_PCR_SHIM_POLICY] = "shim-policy",
7770 [TPM2_PCR_SYSTEM_IDENTITY] = "system-identity",
7771 [TPM2_PCR_DEBUG] = "debug",
7772 [TPM2_PCR_APPLICATION_SUPPORT] = "application-support",
7773 };
7774
7775 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index, int, TPM2_PCRS_MAX - 1);
7776 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index, int);