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