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