1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "creds-util.h"
8 #include "cryptsetup-util.h"
9 #include "dirent-util.h"
10 #include "dlfcn-util.h"
12 #include "extract-word.h"
15 #include "format-table.h"
17 #include "hexdecoct.h"
19 #include "initrd-util.h"
21 #include "lock-util.h"
23 #include "logarithm.h"
24 #include "memory-util.h"
26 #include "nulstr-util.h"
27 #include "parse-util.h"
28 #include "random-util.h"
29 #include "recurse-dir.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"
41 # include <openssl/hmac.h>
45 static void *libtss2_esys_dl
= NULL
;
46 static void *libtss2_rc_dl
= NULL
;
47 static void *libtss2_mu_dl
= NULL
;
49 static DLSYM_FUNCTION(Esys_Create
);
50 static DLSYM_FUNCTION(Esys_CreateLoaded
);
51 static DLSYM_FUNCTION(Esys_CreatePrimary
);
52 static DLSYM_FUNCTION(Esys_EvictControl
);
53 static DLSYM_FUNCTION(Esys_Finalize
);
54 static DLSYM_FUNCTION(Esys_FlushContext
);
55 static DLSYM_FUNCTION(Esys_Free
);
56 static DLSYM_FUNCTION(Esys_GetCapability
);
57 static DLSYM_FUNCTION(Esys_GetRandom
);
58 static DLSYM_FUNCTION(Esys_Import
);
59 static DLSYM_FUNCTION(Esys_Initialize
);
60 static DLSYM_FUNCTION(Esys_Load
);
61 static DLSYM_FUNCTION(Esys_LoadExternal
);
62 static DLSYM_FUNCTION(Esys_NV_DefineSpace
);
63 static DLSYM_FUNCTION(Esys_NV_UndefineSpace
);
64 static DLSYM_FUNCTION(Esys_NV_Write
);
65 static DLSYM_FUNCTION(Esys_PCR_Extend
);
66 static DLSYM_FUNCTION(Esys_PCR_Read
);
67 static DLSYM_FUNCTION(Esys_PolicyAuthValue
);
68 static DLSYM_FUNCTION(Esys_PolicyAuthorize
);
69 static DLSYM_FUNCTION(Esys_PolicyAuthorizeNV
);
70 static DLSYM_FUNCTION(Esys_PolicyGetDigest
);
71 static DLSYM_FUNCTION(Esys_PolicyOR
);
72 static DLSYM_FUNCTION(Esys_PolicyPCR
);
73 static DLSYM_FUNCTION(Esys_PolicySigned
);
74 static DLSYM_FUNCTION(Esys_ReadPublic
);
75 static DLSYM_FUNCTION(Esys_StartAuthSession
);
76 static DLSYM_FUNCTION(Esys_Startup
);
77 static DLSYM_FUNCTION(Esys_TestParms
);
78 static DLSYM_FUNCTION(Esys_TR_Close
);
79 static DLSYM_FUNCTION(Esys_TR_Deserialize
);
80 static DLSYM_FUNCTION(Esys_TR_FromTPMPublic
);
81 static DLSYM_FUNCTION(Esys_TR_GetName
);
82 static DLSYM_FUNCTION(Esys_TR_GetTpmHandle
);
83 static DLSYM_FUNCTION(Esys_TR_Serialize
);
84 static DLSYM_FUNCTION(Esys_TR_SetAuth
);
85 static DLSYM_FUNCTION(Esys_TRSess_GetAttributes
);
86 static DLSYM_FUNCTION(Esys_TRSess_GetNonceTPM
);
87 static DLSYM_FUNCTION(Esys_TRSess_SetAttributes
);
88 static DLSYM_FUNCTION(Esys_Unseal
);
89 static DLSYM_FUNCTION(Esys_VerifySignature
);
91 static DLSYM_FUNCTION(Tss2_MU_TPM2_CC_Marshal
);
92 static DLSYM_FUNCTION(Tss2_MU_TPM2_HANDLE_Marshal
);
93 static DLSYM_FUNCTION(Tss2_MU_TPM2B_DIGEST_Marshal
);
94 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal
);
95 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal
);
96 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NAME_Marshal
);
97 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Marshal
);
98 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Unmarshal
);
99 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Marshal
);
100 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Unmarshal
);
101 static DLSYM_FUNCTION(Tss2_MU_TPM2B_SENSITIVE_Marshal
);
102 static DLSYM_FUNCTION(Tss2_MU_TPML_PCR_SELECTION_Marshal
);
103 static DLSYM_FUNCTION(Tss2_MU_TPMS_NV_PUBLIC_Marshal
);
104 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Marshal
);
105 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal
);
106 static DLSYM_FUNCTION(Tss2_MU_TPMS_ECC_POINT_Marshal
);
107 static DLSYM_FUNCTION(Tss2_MU_TPMT_HA_Marshal
);
108 static DLSYM_FUNCTION(Tss2_MU_TPMT_PUBLIC_Marshal
);
109 static DLSYM_FUNCTION(Tss2_MU_UINT32_Marshal
);
111 static DLSYM_FUNCTION(Tss2_RC_Decode
);
113 int dlopen_tpm2(void) {
116 ELF_NOTE_DLOPEN("tpm",
118 ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
,
119 "libtss2-esys.so.0");
121 r
= dlopen_many_sym_or_warn(
122 &libtss2_esys_dl
, "libtss2-esys.so.0", LOG_DEBUG
,
123 DLSYM_ARG(Esys_Create
),
124 DLSYM_ARG(Esys_CreateLoaded
),
125 DLSYM_ARG(Esys_CreatePrimary
),
126 DLSYM_ARG(Esys_EvictControl
),
127 DLSYM_ARG(Esys_Finalize
),
128 DLSYM_ARG(Esys_FlushContext
),
129 DLSYM_ARG(Esys_Free
),
130 DLSYM_ARG(Esys_GetCapability
),
131 DLSYM_ARG(Esys_GetRandom
),
132 DLSYM_ARG(Esys_Import
),
133 DLSYM_ARG(Esys_Initialize
),
134 DLSYM_ARG(Esys_Load
),
135 DLSYM_ARG(Esys_LoadExternal
),
136 DLSYM_ARG(Esys_NV_DefineSpace
),
137 DLSYM_ARG(Esys_NV_UndefineSpace
),
138 DLSYM_ARG(Esys_NV_Write
),
139 DLSYM_ARG(Esys_PCR_Extend
),
140 DLSYM_ARG(Esys_PCR_Read
),
141 DLSYM_ARG(Esys_PolicyAuthValue
),
142 DLSYM_ARG(Esys_PolicyAuthorize
),
143 DLSYM_ARG(Esys_PolicyAuthorizeNV
),
144 DLSYM_ARG(Esys_PolicyGetDigest
),
145 DLSYM_ARG(Esys_PolicyOR
),
146 DLSYM_ARG(Esys_PolicyPCR
),
147 DLSYM_ARG(Esys_PolicySigned
),
148 DLSYM_ARG(Esys_ReadPublic
),
149 DLSYM_ARG(Esys_StartAuthSession
),
150 DLSYM_ARG(Esys_Startup
),
151 DLSYM_ARG(Esys_TestParms
),
152 DLSYM_ARG(Esys_TR_Close
),
153 DLSYM_ARG(Esys_TR_Deserialize
),
154 DLSYM_ARG(Esys_TR_FromTPMPublic
),
155 DLSYM_ARG(Esys_TR_GetName
),
156 DLSYM_ARG(Esys_TR_Serialize
),
157 DLSYM_ARG(Esys_TR_SetAuth
),
158 DLSYM_ARG(Esys_TRSess_GetAttributes
),
159 DLSYM_ARG(Esys_TRSess_GetNonceTPM
),
160 DLSYM_ARG(Esys_TRSess_SetAttributes
),
161 DLSYM_ARG(Esys_Unseal
),
162 DLSYM_ARG(Esys_VerifySignature
));
166 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
167 * version of 2.4.0 this sym can be moved up to the normal list above. */
168 r
= dlsym_many_or_warn(libtss2_esys_dl
, LOG_DEBUG
, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle
));
170 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
172 ELF_NOTE_DLOPEN("tpm",
174 ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
,
177 r
= dlopen_many_sym_or_warn(
178 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
179 DLSYM_ARG(Tss2_RC_Decode
));
183 ELF_NOTE_DLOPEN("tpm",
185 ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
,
188 return dlopen_many_sym_or_warn(
189 &libtss2_mu_dl
, "libtss2-mu.so.0", LOG_DEBUG
,
190 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal
),
191 DLSYM_ARG(Tss2_MU_TPM2_HANDLE_Marshal
),
192 DLSYM_ARG(Tss2_MU_TPM2B_DIGEST_Marshal
),
193 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal
),
194 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal
),
195 DLSYM_ARG(Tss2_MU_TPM2B_NAME_Marshal
),
196 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal
),
197 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal
),
198 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal
),
199 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal
),
200 DLSYM_ARG(Tss2_MU_TPM2B_SENSITIVE_Marshal
),
201 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal
),
202 DLSYM_ARG(Tss2_MU_TPMS_NV_PUBLIC_Marshal
),
203 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Marshal
),
204 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal
),
205 DLSYM_ARG(Tss2_MU_TPMS_ECC_POINT_Marshal
),
206 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal
),
207 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal
),
208 DLSYM_ARG(Tss2_MU_UINT32_Marshal
));
211 void Esys_Freep(void *p
) {
213 sym_Esys_Free(*(void**) p
);
216 /* Get a specific TPM capability (or capabilities).
218 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
219 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
220 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
221 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
223 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
224 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
225 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
226 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
227 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
228 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
229 * capability category may have more specific requirements than described here; see the spec for exact
231 static int tpm2_get_capability(
236 TPMU_CAPABILITIES
*ret_capability_data
) {
238 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
244 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
245 capability
, property
, count
);
247 rc
= sym_Esys_GetCapability(
257 if (rc
== TPM2_RC_VALUE
)
258 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
),
259 "Requested TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" apparently doesn't exist: %s",
260 capability
, property
, sym_Tss2_RC_Decode(rc
));
261 if (rc
!= TSS2_RC_SUCCESS
)
262 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
263 "Failed to get TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
": %s",
264 capability
, property
, sym_Tss2_RC_Decode(rc
));
265 if (capabilities
->capability
!= capability
)
266 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
267 "TPM provided wrong capability: 0x%04" PRIx32
" instead of 0x%04" PRIx32
".",
268 capabilities
->capability
, capability
);
270 if (ret_capability_data
)
271 *ret_capability_data
= capabilities
->data
;
273 return more
== TPM2_YES
;
276 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
278 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
279 TPMU_CAPABILITIES capability
;
284 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
285 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
286 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
287 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
288 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
289 * changed while we are performing some operation, it's reasonable to assume it will break us even if
290 * we don't cache the algorithms, thus they should be "safe" to cache. */
291 TPM2_ALG_ID current_alg
= TPM2_ALG_FIRST
;
293 r
= tpm2_get_capability(
296 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
302 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
304 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
305 * there are no more. */
306 assert(algorithms
.count
> 0);
308 if (!GREEDY_REALLOC_APPEND(
309 c
->capability_algorithms
,
310 c
->n_capability_algorithms
,
311 algorithms
.algProperties
,
313 return log_oom_debug();
318 /* Set current_alg to alg id after last alg id the TPM provided */
319 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
322 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
323 * while running, but that would be crazy, so let's hope it is not possible. */
324 TPM2_CC current_cc
= TPM2_CC_FIRST
;
326 r
= tpm2_get_capability(
335 TPML_CCA commands
= capability
.command
;
337 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
338 * there are no more. */
339 assert(commands
.count
> 0);
341 if (!GREEDY_REALLOC_APPEND(
342 c
->capability_commands
,
343 c
->n_capability_commands
,
344 commands
.commandAttributes
,
346 return log_oom_debug();
351 /* Set current_cc to index after last cc the TPM provided */
352 current_cc
= TPMA_CC_TO_TPM2_CC(commands
.commandAttributes
[commands
.count
- 1]) + 1;
355 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
356 * while running, but that would be crazy, so let's hope it is not possible. */
357 TPM2_ECC_CURVE current_ecc_curve
= TPM2_ECC_NONE
;
359 r
= tpm2_get_capability(
365 if (r
== -ENXIO
) /* If the TPM doesn't support ECC, it might return TPM2_RC_VALUE rather than capability.eccCurves == 0 */
370 TPML_ECC_CURVE ecc_curves
= capability
.eccCurves
;
372 /* ECC support isn't required */
373 if (ecc_curves
.count
== 0)
376 if (!GREEDY_REALLOC_APPEND(
377 c
->capability_ecc_curves
,
378 c
->n_capability_ecc_curves
,
379 ecc_curves
.eccCurves
,
381 return log_oom_debug();
386 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
387 current_ecc_curve
= ecc_curves
.eccCurves
[ecc_curves
.count
- 1] + 1;
390 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
391 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
392 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
393 * safely assume the TPM PCR allocation will not change while we are using it. */
394 r
= tpm2_get_capability(
403 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
404 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
405 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
406 * this command with the full PCR allocation and moreData will be NO." */
407 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
408 c
->capability_pcrs
= capability
.assignedPCR
;
413 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
414 * TPMA_ALGORITHM is provided, otherwise false. */
415 static bool tpm2_get_capability_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
, TPMA_ALGORITHM
*ret
) {
418 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
419 if (alg_prop
->alg
== alg
) {
421 *ret
= alg_prop
->algProperties
;
425 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
432 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
433 return tpm2_get_capability_alg(c
, alg
, NULL
);
436 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
437 * otherwise false. */
438 static bool tpm2_get_capability_command(Tpm2Context
*c
, TPM2_CC command
, TPMA_CC
*ret
) {
441 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
442 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
448 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
455 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
456 return tpm2_get_capability_command(c
, command
, NULL
);
459 /* Returns true if the TPM supports the ECC curve, otherwise false. */
460 bool tpm2_supports_ecc_curve(Tpm2Context
*c
, TPM2_ECC_CURVE ecc_curve
) {
463 FOREACH_ARRAY(curve
, c
->capability_ecc_curves
, c
->n_capability_ecc_curves
)
464 if (*curve
== ecc_curve
)
467 log_debug("TPM does not support ECC curve 0x%" PRIx16
".", ecc_curve
);
471 /* Query the TPM for populated handles.
473 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
474 * contain only populated handle addresses (which might not include the requested handle). The number of
475 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
476 * range (i.e. handle & 0xff000000).
478 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
479 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
480 static int tpm2_get_capability_handles(
484 TPM2_HANDLE
**ret_handles
,
485 size_t *ret_n_handles
) {
487 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
488 size_t n_handles
= 0;
489 TPM2_HANDLE current
= start
;
494 assert(ret_n_handles
);
496 max
= MIN(max
, UINT32_MAX
);
499 TPMU_CAPABILITIES capability
;
500 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
504 TPML_HANDLE handle_list
= capability
.handles
;
505 if (handle_list
.count
== 0)
508 assert(handle_list
.count
<= max
);
510 if (n_handles
> SIZE_MAX
- handle_list
.count
)
511 return log_oom_debug();
513 if (!GREEDY_REALLOC_APPEND(handles
, n_handles
, handle_list
.handle
, handle_list
.count
))
514 return log_oom_debug();
516 max
-= handle_list
.count
;
518 /* Update current to the handle index after the last handle in the list. */
519 current
= handles
[n_handles
- 1] + 1;
522 /* No more handles in this range. */
526 *ret_handles
= TAKE_PTR(handles
);
527 *ret_n_handles
= n_handles
;
532 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
533 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
535 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
536 static int tpm2_get_capability_handle(Tpm2Context
*c
, TPM2_HANDLE handle
) {
537 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
538 size_t n_handles
= 0;
541 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
545 return n_handles
== 0 ? false : handles
[0] == handle
;
548 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
549 bool tpm2_test_parms(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, const TPMU_PUBLIC_PARMS
*parms
) {
555 TPMT_PUBLIC_PARMS parameters
= {
557 .parameters
= *parms
,
560 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
561 if (rc
!= TSS2_RC_SUCCESS
)
562 /* The spec says if the parms are not supported the TPM returns "...the appropriate
563 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
564 * unmarshaling errors, instead of checking for them all here, let's just assume any error
565 * indicates unsupported parms, and log the specific error text. */
566 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc
));
568 return rc
== TSS2_RC_SUCCESS
;
571 static bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
575 return tpm2_test_parms(c
, public->type
, &public->parameters
);
578 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
582 TPMU_PUBLIC_PARMS parms
= {
583 .symDetail
.sym
= *parameters
,
586 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
589 static bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
593 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
594 * functionally identical. */
595 TPMT_SYM_DEF_OBJECT object
= {
596 .algorithm
= parameters
->algorithm
,
597 .keyBits
= parameters
->keyBits
,
598 .mode
= parameters
->mode
,
601 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
604 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
609 sym_Esys_Finalize(&c
->esys_context
);
611 c
->tcti_context
= mfree(c
->tcti_context
);
612 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
614 c
->capability_algorithms
= mfree(c
->capability_algorithms
);
615 c
->capability_commands
= mfree(c
->capability_commands
);
616 c
->capability_ecc_curves
= mfree(c
->capability_ecc_curves
);
621 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
623 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
624 .algorithm
= TPM2_ALG_AES
,
626 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
629 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
630 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
636 context
= new(Tpm2Context
, 1);
638 return log_oom_debug();
640 *context
= (Tpm2Context
) {
646 return log_debug_errno(r
, "TPM2 support not installed: %m");
649 device
= secure_getenv("SYSTEMD_TPM2_DEVICE");
651 /* Setting the env var to an empty string forces tpm2-tss' own device picking
652 * logic to be used. */
653 device
= empty_to_null(device
);
655 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
656 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
657 * might be used and we really don't want that, since it is a system service and that creates
658 * various ordering issues/deadlocks during early boot. */
659 device
= "device:/dev/tpmrm0";
663 const char *param
, *driver
, *fn
;
664 const TSS2_TCTI_INFO
* info
;
665 TSS2_TCTI_INFO_FUNC func
;
668 param
= strchr(device
, ':');
670 /* Syntax #1: Pair of driver string and arbitrary parameter */
671 driver
= strndupa_safe(device
, param
- device
);
673 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
676 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
677 /* Syntax #2: TPM device node */
681 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
683 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
685 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
687 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
688 if (!filename_is_valid(fn
))
689 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name '%s' not valid, refusing.", driver
);
691 context
->tcti_dl
= dlopen(fn
, RTLD_NOW
);
692 if (!context
->tcti_dl
)
693 return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG
), "Failed to load %s: %s", fn
, dlerror());
695 log_debug("Loaded '%s' via dlopen()", fn
);
697 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
699 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
700 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
705 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
707 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
709 rc
= info
->init(/* context= */ NULL
, &sz
, /* param= */ NULL
);
710 if (rc
!= TPM2_RC_SUCCESS
)
711 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
712 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
714 context
->tcti_context
= malloc0(sz
);
715 if (!context
->tcti_context
)
716 return log_oom_debug();
718 rc
= info
->init(context
->tcti_context
, &sz
, param
);
719 if (rc
!= TPM2_RC_SUCCESS
)
720 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
721 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
724 rc
= sym_Esys_Initialize(&context
->esys_context
, context
->tcti_context
, NULL
);
725 if (rc
!= TSS2_RC_SUCCESS
)
726 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
727 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc
));
729 rc
= sym_Esys_Startup(context
->esys_context
, TPM2_SU_CLEAR
);
730 if (rc
== TPM2_RC_INITIALIZE
)
731 log_debug("TPM already started up.");
732 else if (rc
== TSS2_RC_SUCCESS
)
733 log_debug("TPM successfully started up.");
735 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
736 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
738 r
= tpm2_cache_capabilities(context
);
740 return log_debug_errno(r
, "Failed to cache TPM capabilities: %m");
742 /* We require AES and CFB support for session encryption. */
743 if (!tpm2_supports_alg(context
, TPM2_ALG_AES
))
744 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM does not support AES.");
746 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
747 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM does not support CFB.");
749 if (!tpm2_supports_tpmt_sym_def(context
, &SESSION_TEMPLATE_SYM_AES_128_CFB
))
750 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM does not support AES-128-CFB.");
752 *ret_context
= TAKE_PTR(context
);
757 int tpm2_context_new_or_warn(const char *device
, Tpm2Context
**ret_context
) {
762 r
= tpm2_context_new(device
, ret_context
);
763 if (r
== -EOPNOTSUPP
)
764 return log_error_errno(r
, "TPM device not usable as it does not support the required functionality (AES-128-CFB missing?).");
766 return log_error_errno(r
, "TPM TCTI driver not available.");
768 return log_error_errno(r
, "TPM device not found.");
770 return log_error_errno(r
, "Failed to create TPM2 context: %m");
775 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
778 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
781 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
782 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
783 * as removing its corresponding handle from the actual TPM. */
785 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
787 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
788 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
789 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
790 * directly affects us; for example the src/test/test-tpm2.c test function
791 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
792 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
793 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
794 * references will be cleaned up when we free our ESYS_CONTEXT.
796 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
797 rc
= TSS2_RC_SUCCESS
; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
798 if (rc
!= TSS2_RC_SUCCESS
)
799 /* We ignore failures here (besides debug logging), since this is called in error paths,
800 * where we cannot do anything about failures anymore. And when it is called in successful
801 * codepaths by this time we already did what we wanted to do, and got the results we wanted
802 * so there's no reason to make this fail more loudly than necessary. */
803 log_debug("Failed to %s TPM handle, ignoring: %s", flush
? "flush" : "close", sym_Tss2_RC_Decode(rc
));
806 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
810 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
812 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
814 return mfree(handle
);
817 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
818 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
822 handle
= new(Tpm2Handle
, 1);
824 return log_oom_debug();
826 *handle
= (Tpm2Handle
) {
827 .tpm2_context
= tpm2_context_ref(context
),
828 .esys_handle
= ESYS_TR_NONE
,
832 *ret_handle
= TAKE_PTR(handle
);
837 static int tpm2_read_public(
839 const Tpm2Handle
*session
,
840 const Tpm2Handle
*handle
,
841 TPM2B_PUBLIC
**ret_public
,
842 TPM2B_NAME
**ret_name
,
843 TPM2B_NAME
**ret_qname
) {
850 rc
= sym_Esys_ReadPublic(
853 session
? session
->esys_handle
: ESYS_TR_NONE
,
859 if (rc
!= TSS2_RC_SUCCESS
)
860 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
861 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
866 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
867 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
868 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
869 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
871 int tpm2_index_to_handle(
874 const Tpm2Handle
*session
,
875 TPM2B_PUBLIC
**ret_public
,
876 TPM2B_NAME
**ret_name
,
877 TPM2B_NAME
**ret_qname
,
878 Tpm2Handle
**ret_handle
) {
885 /* Only allow persistent, transient, or NV index handle types. */
886 switch (TPM2_HANDLE_TYPE(index
)) {
887 case TPM2_HT_PERSISTENT
:
888 case TPM2_HT_NV_INDEX
:
889 case TPM2_HT_TRANSIENT
:
892 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
893 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
894 "Invalid handle 0x%08" PRIx32
" (in PCR range).", index
);
895 case TPM2_HT_HMAC_SESSION
:
896 case TPM2_HT_POLICY_SESSION
:
897 /* Session indexes are only used internally by tpm2-tss (or lower code) */
898 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
899 "Invalid handle 0x%08" PRIx32
" (in session range).", index
);
900 case TPM2_HT_PERMANENT
:
901 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
902 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
903 "Invalid handle 0x%08" PRIx32
" (in permanent range).", index
);
905 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
906 "Invalid handle 0x%08" PRIx32
" (in unknown range).", index
);
909 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
910 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
911 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
912 if (TPM2_HANDLE_TYPE(index
) != TPM2_HT_TRANSIENT
) { // FIXME: once kernel bug is fixed, check transient handles too
913 r
= tpm2_get_capability_handle(c
, index
);
917 log_debug("TPM handle 0x%08" PRIx32
" not populated.", index
);
930 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
931 r
= tpm2_handle_new(c
, &handle
);
935 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
936 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
937 handle
->flush
= false;
939 rc
= sym_Esys_TR_FromTPMPublic(
942 session
? session
->esys_handle
: ESYS_TR_NONE
,
945 &handle
->esys_handle
);
946 if (rc
!= TSS2_RC_SUCCESS
)
947 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
948 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
950 if (ret_public
|| ret_name
|| ret_qname
) {
951 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
957 *ret_handle
= TAKE_PTR(handle
);
962 /* Get the handle index for the provided Tpm2Handle. */
963 int tpm2_index_from_handle(Tpm2Context
*c
, const Tpm2Handle
*handle
, TPM2_HANDLE
*ret_index
) {
970 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
971 * version of 2.4.0 this check can be removed. */
972 if (!sym_Esys_TR_GetTpmHandle
)
973 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
974 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
976 rc
= sym_Esys_TR_GetTpmHandle(c
->esys_context
, handle
->esys_handle
, ret_index
);
977 if (rc
!= TSS2_RC_SUCCESS
)
978 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
979 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc
));
984 /* Copy an object in the TPM at a transient handle to a persistent handle.
986 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
987 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
988 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
991 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
992 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
993 * at the requested persistent handle index (or the first available if none was requested).
995 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
996 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
997 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
998 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
999 * memory for persistent storage. The persistent handle is only provided when returning 1. */
1000 static int tpm2_persist_handle(
1002 const Tpm2Handle
*transient_handle
,
1003 const Tpm2Handle
*session
,
1004 TPMI_DH_PERSISTENT persistent_handle_index
,
1005 Tpm2Handle
**ret_persistent_handle
) {
1007 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
1008 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
1009 TPMI_DH_PERSISTENT first
= UINT32_C(0x81000000), last
= UINT32_C(0x81ffffff);
1014 assert(transient_handle
);
1016 /* If persistent handle index specified, only try that. */
1017 if (persistent_handle_index
!= 0) {
1018 if (TPM2_HANDLE_TYPE(persistent_handle_index
) != TPM2_HT_PERSISTENT
)
1019 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
1020 "Handle not in persistent range: 0x%x", persistent_handle_index
);
1022 first
= last
= persistent_handle_index
;
1025 for (TPMI_DH_PERSISTENT requested
= first
; requested
<= last
; requested
++) {
1026 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*persistent_handle
= NULL
;
1027 r
= tpm2_handle_new(c
, &persistent_handle
);
1031 /* Since this is a persistent handle, don't flush it. */
1032 persistent_handle
->flush
= false;
1034 rc
= sym_Esys_EvictControl(
1037 transient_handle
->esys_handle
,
1038 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
1042 &persistent_handle
->esys_handle
);
1043 if (rc
== TSS2_RC_SUCCESS
) {
1044 if (ret_persistent_handle
)
1045 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
1049 if (rc
!= TPM2_RC_NV_DEFINED
)
1050 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1051 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc
));
1054 if (ret_persistent_handle
)
1055 *ret_persistent_handle
= NULL
;
1060 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
1062 static int tpm2_credit_random(Tpm2Context
*c
) {
1063 size_t rps
, done
= 0;
1070 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
1071 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
1072 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
1075 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH
, F_OK
) < 0) {
1076 if (errno
!= ENOENT
)
1077 log_debug_errno(errno
, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH
"' exists, ignoring: %m");
1079 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
1080 return 0; /* Already done */
1083 t
= now(CLOCK_MONOTONIC
);
1085 for (rps
= random_pool_size(); rps
> 0;) {
1086 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
1088 rc
= sym_Esys_GetRandom(
1093 MIN(rps
, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1095 if (rc
!= TSS2_RC_SUCCESS
)
1096 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1097 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc
));
1099 if (buffer
->size
== 0)
1100 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1101 "Zero-sized entropy returned from TPM.");
1103 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
1105 return log_debug_errno(r
, "Failed wo write entropy to kernel: %m");
1107 done
+= buffer
->size
;
1108 rps
= LESS_BY(rps
, buffer
->size
);
1111 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
1113 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
1115 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
1120 /* Get one of the legacy primary key templates.
1122 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1123 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1124 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1125 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1126 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1127 /* Do not modify. */
1128 static const TPMT_PUBLIC legacy_ecc
= {
1129 .type
= TPM2_ALG_ECC
,
1130 .nameAlg
= TPM2_ALG_SHA256
,
1132 TPMA_OBJECT_RESTRICTED
|
1133 TPMA_OBJECT_DECRYPT
|
1134 TPMA_OBJECT_FIXEDTPM
|
1135 TPMA_OBJECT_FIXEDPARENT
|
1136 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1137 TPMA_OBJECT_USERWITHAUTH
,
1138 .parameters
.eccDetail
= {
1140 .algorithm
= TPM2_ALG_AES
,
1142 .mode
.aes
= TPM2_ALG_CFB
,
1144 .scheme
.scheme
= TPM2_ALG_NULL
,
1145 .curveID
= TPM2_ECC_NIST_P256
,
1146 .kdf
.scheme
= TPM2_ALG_NULL
,
1150 /* Do not modify. */
1151 static const TPMT_PUBLIC legacy_rsa
= {
1152 .type
= TPM2_ALG_RSA
,
1153 .nameAlg
= TPM2_ALG_SHA256
,
1154 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
1155 .parameters
.rsaDetail
= {
1157 .algorithm
= TPM2_ALG_AES
,
1159 .mode
.aes
= TPM2_ALG_CFB
,
1161 .scheme
.scheme
= TPM2_ALG_NULL
,
1166 assert(ret_template
);
1168 if (alg
== TPM2_ALG_ECC
)
1169 *ret_template
= legacy_ecc
;
1170 else if (alg
== TPM2_ALG_RSA
)
1171 *ret_template
= legacy_rsa
;
1173 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1174 "Unsupported legacy SRK alg: 0x%x", alg
);
1179 /* Get a Storage Root Key (SRK) template.
1181 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1182 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1183 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1184 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1187 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1188 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1190 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1191 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1192 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1194 * Returns 0 if the specified algorithm is ECC or RSA, otherwise -EOPNOTSUPP. */
1195 int tpm2_get_srk_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1196 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1197 * Provisioning Guidance document, specifically:
1198 * TPMA_OBJECT_USERWITHAUTH is added.
1199 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1200 * TPMA_OBJECT_NODA is added. */
1201 TPMA_OBJECT srk_attributes
=
1202 TPMA_OBJECT_DECRYPT
|
1203 TPMA_OBJECT_FIXEDPARENT
|
1204 TPMA_OBJECT_FIXEDTPM
|
1206 TPMA_OBJECT_RESTRICTED
|
1207 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1208 TPMA_OBJECT_USERWITHAUTH
;
1210 /* The symmetric configuration is the same between ECC and RSA templates. */
1211 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1212 .algorithm
= TPM2_ALG_AES
,
1214 .mode
.aes
= TPM2_ALG_CFB
,
1217 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1219 /* From the EK Credential Profile template "L-2". */
1220 TPMT_PUBLIC srk_ecc
= {
1221 .type
= TPM2_ALG_ECC
,
1222 .nameAlg
= TPM2_ALG_SHA256
,
1223 .objectAttributes
= srk_attributes
,
1224 .parameters
.eccDetail
= {
1225 .symmetric
= srk_symmetric
,
1226 .scheme
.scheme
= TPM2_ALG_NULL
,
1227 .curveID
= TPM2_ECC_NIST_P256
,
1228 .kdf
.scheme
= TPM2_ALG_NULL
,
1232 /* From the EK Credential Profile template "L-1". */
1233 TPMT_PUBLIC srk_rsa
= {
1234 .type
= TPM2_ALG_RSA
,
1235 .nameAlg
= TPM2_ALG_SHA256
,
1236 .objectAttributes
= srk_attributes
,
1237 .parameters
.rsaDetail
= {
1238 .symmetric
= srk_symmetric
,
1239 .scheme
.scheme
= TPM2_ALG_NULL
,
1244 assert(ret_template
);
1248 *ret_template
= srk_ecc
;
1251 *ret_template
= srk_rsa
;
1255 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "No SRK for algorithm 0x%" PRIx16
, alg
);
1258 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1259 int tpm2_get_best_srk_template(Tpm2Context
*c
, TPMT_PUBLIC
*ret_template
) {
1260 TPMT_PUBLIC
template;
1264 assert(ret_template
);
1266 r
= tpm2_get_srk_template(TPM2_ALG_ECC
, &template);
1270 if (!tpm2_supports_alg(c
, TPM2_ALG_ECC
))
1271 log_debug("TPM does not support ECC.");
1272 else if (!tpm2_supports_ecc_curve(c
, template.parameters
.eccDetail
.curveID
))
1273 log_debug("TPM does not support ECC-NIST-P256 curve.");
1274 else if (!tpm2_supports_tpmt_public(c
, &template))
1275 log_debug("TPM does not support SRK ECC template L-2.");
1277 *ret_template
= template;
1281 r
= tpm2_get_srk_template(TPM2_ALG_RSA
, &template);
1285 if (!tpm2_supports_alg(c
, TPM2_ALG_RSA
))
1286 log_debug("TPM does not support RSA.");
1287 else if (!tpm2_supports_tpmt_public(c
, &template))
1288 log_debug("TPM does not support SRK RSA template L-1.");
1290 *ret_template
= template;
1294 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1295 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1298 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1299 * tpm2_get_or_create_srk() below. */
1302 const Tpm2Handle
*session
,
1303 TPM2B_PUBLIC
**ret_public
,
1304 TPM2B_NAME
**ret_name
,
1305 TPM2B_NAME
**ret_qname
,
1306 Tpm2Handle
**ret_handle
) {
1308 return tpm2_index_to_handle(c
, TPM2_SRK_HANDLE
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1311 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1312 * exists, or < 0 on error. */
1313 int tpm2_get_or_create_srk(
1315 const Tpm2Handle
*session
,
1316 TPM2B_PUBLIC
**ret_public
,
1317 TPM2B_NAME
**ret_name
,
1318 TPM2B_NAME
**ret_qname
,
1319 Tpm2Handle
**ret_handle
) {
1323 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1327 return 0; /* 0 → SRK already set up */
1329 /* No SRK, create and persist one */
1330 TPM2B_PUBLIC
template = {
1331 .size
= sizeof(TPMT_PUBLIC
),
1333 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1335 return log_debug_errno(r
, "Could not get best SRK template: %m");
1337 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1338 r
= tpm2_create_primary(
1342 /* sensitive= */ NULL
,
1343 /* ret_public= */ NULL
,
1348 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1349 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1350 * either case, all threads will get the persistent SRK below. */
1351 r
= tpm2_persist_handle(c
, transient_handle
, session
, TPM2_SRK_HANDLE
, /* ret_persistent_handle= */ NULL
);
1355 /* The SRK should exist now. */
1356 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1360 /* This should never happen. */
1361 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1363 return 1; /* > 0 → SRK newly set up */
1366 /* Utility functions for TPMS_PCR_SELECTION. */
1368 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1369 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1371 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1374 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1375 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
1379 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1380 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPMS_PCR_SELECTION
*ret
) {
1383 /* This is currently hardcoded at 24 PCRs, above. */
1384 if (!TPM2_PCR_MASK_VALID(mask
))
1385 log_debug("PCR mask selections (%x) out of range, ignoring.",
1386 mask
& ~((uint32_t)TPM2_PCRS_MASK
));
1388 *ret
= (TPMS_PCR_SELECTION
){
1390 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1391 .pcrSelect
[0] = mask
& 0xff,
1392 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1393 .pcrSelect
[2] = (mask
>> 16) & 0xff,
1397 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1398 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1401 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1404 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1407 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
1410 /* Add all PCR selections in the mask. */
1411 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1412 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 1);
1415 /* Remove all PCR selections in the mask. */
1416 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1417 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 0);
1420 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1421 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1424 assert(a
->hash
== b
->hash
);
1426 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1429 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1430 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1433 assert(a
->hash
== b
->hash
);
1435 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1438 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1439 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION
*a
, TPMS_PCR_SELECTION
*b
) {
1443 tpm2_tpms_pcr_selection_add(a
, b
);
1444 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
1447 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1448 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1449 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1450 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1451 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1453 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1454 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1456 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1457 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1458 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1460 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1463 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1465 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1469 return strjoin(algstr
, "(", mask
, ")");
1472 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1475 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1478 /* Utility functions for TPML_PCR_SELECTION. */
1480 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1481 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION
*l
, uint32_t index
) {
1483 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1484 assert(index
< l
->count
);
1486 size_t s
= l
->count
- (index
+ 1);
1487 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
1491 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1492 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1493 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1494 static TPMS_PCR_SELECTION
*tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1495 TPML_PCR_SELECTION
*l
,
1496 TPMI_ALG_HASH hash_alg
) {
1499 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1501 TPMS_PCR_SELECTION
*selection
= NULL
;
1502 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1503 if (s
->hash
== hash_alg
) {
1511 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1512 for (uint32_t i
= l
->count
- 1; i
> 0; i
--) {
1513 TPMS_PCR_SELECTION
*s
= &l
->pcrSelections
[i
];
1518 if (s
->hash
== hash_alg
) {
1519 tpm2_tpms_pcr_selection_move(selection
, s
);
1520 tpm2_tpml_pcr_selection_remove_index(l
, i
);
1527 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1528 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION
*l
) {
1529 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1530 for (uint32_t i
= 0; i
< l
->count
; i
++)
1531 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1532 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, l
->pcrSelections
[i
].hash
);
1535 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1536 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash_alg
) {
1539 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1540 * are multiple entries with the requested hash alg. */
1541 TPML_PCR_SELECTION lcopy
= *l
;
1543 TPMS_PCR_SELECTION
*s
;
1544 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1548 return tpm2_tpms_pcr_selection_to_mask(s
);
1551 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1552 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPML_PCR_SELECTION
*ret
) {
1555 TPMS_PCR_SELECTION s
;
1556 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1558 *ret
= (TPML_PCR_SELECTION
){
1560 .pcrSelections
[0] = s
,
1564 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1565 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1566 * entries with the same hash alg. */
1567 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1571 if (tpm2_tpms_pcr_selection_is_empty(s
))
1574 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1576 tpm2_tpms_pcr_selection_add(selection
, s
);
1580 /* It's already broken if the count is higher than the array has size for. */
1581 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1583 /* If full, the cleanup should result in at least one available entry. */
1584 if (l
->count
== ELEMENTSOF(l
->pcrSelections
))
1585 tpm2_tpml_pcr_selection_cleanup(l
);
1587 assert(l
->count
< ELEMENTSOF(l
->pcrSelections
));
1588 l
->pcrSelections
[l
->count
++] = *s
;
1591 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1592 * will combine all entries for 's->hash' in 'l'. */
1593 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1597 if (tpm2_tpms_pcr_selection_is_empty(s
))
1600 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1602 tpm2_tpms_pcr_selection_sub(selection
, s
);
1605 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1606 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1609 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l
, hash
), mask
);
1612 /* Add the PCR selections in the mask, with the provided hash. */
1613 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1614 TPMS_PCR_SELECTION tpms
;
1618 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1619 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l
, &tpms
);
1622 /* Remove the PCR selections in the mask, with the provided hash. */
1623 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1624 TPMS_PCR_SELECTION tpms
;
1628 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1629 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l
, &tpms
);
1632 /* Add all PCR selections in 'b' to 'a'. */
1633 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1637 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1638 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a
, selection_b
);
1641 /* Remove all PCR selections in 'b' from 'a'. */
1642 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1646 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1647 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a
, selection_b
);
1650 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION
*l
) {
1653 _cleanup_free_
char *banks
= NULL
;
1654 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1655 if (tpm2_tpms_pcr_selection_is_empty(s
))
1658 _cleanup_free_
char *str
= tpm2_tpms_pcr_selection_to_string(s
);
1659 if (!str
|| !strextend_with_separator(&banks
, ",", str
))
1663 return strjoin("[", strempty(banks
), "]");
1666 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION
*l
) {
1668 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1671 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1672 size_t w
= tpm2_tpms_pcr_selection_weight(s
);
1673 assert(weight
<= SIZE_MAX
- w
);
1680 bool tpm2_pcr_value_valid(const Tpm2PCRValue
*pcr_value
) {
1686 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1687 log_debug("PCR index %u invalid.", pcr_value
->index
);
1691 /* If it contains a value, the value size must match the hash size. */
1692 if (pcr_value
->value
.size
> 0) {
1693 r
= tpm2_hash_alg_to_size(pcr_value
->hash
);
1697 if (pcr_value
->value
.size
!= (size_t) r
) {
1698 log_debug("PCR hash 0x%" PRIx16
" expected size %d does not match actual size %" PRIu16
".",
1699 pcr_value
->hash
, r
, pcr_value
->value
.size
);
1707 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1709 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1710 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1712 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1714 bool tpm2_pcr_values_valid(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1715 if (!pcr_values
&& n_pcr_values
> 0)
1718 const Tpm2PCRValue
*previous
= NULL
;
1719 FOREACH_ARRAY(current
, pcr_values
, n_pcr_values
) {
1720 if (!tpm2_pcr_value_valid(current
))
1728 /* Hashes must be sorted in ascending order */
1729 if (current
->hash
< previous
->hash
) {
1730 log_debug("PCR values not in ascending order, hash %" PRIu16
" is after %" PRIu16
".",
1731 current
->hash
, previous
->hash
);
1735 if (current
->hash
== previous
->hash
) {
1736 /* Indexes (for the same hash) must be sorted in ascending order */
1737 if (current
->index
< previous
->index
) {
1738 log_debug("PCR values not in ascending order, hash %" PRIu16
" index %u is after %u.",
1739 current
->hash
, current
->index
, previous
->index
);
1743 /* Indexes (for the same hash) must not be duplicates */
1744 if (current
->index
== previous
->index
) {
1745 log_debug("PCR values contain duplicates for hash %" PRIu16
" index %u.",
1746 current
->hash
, previous
->index
);
1755 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1756 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1757 assert(pcr_values
|| n_pcr_values
== 0);
1759 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1760 if (v
->value
.size
> 0)
1766 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1767 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1768 assert(pcr_values
|| n_pcr_values
== 0);
1770 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1771 if (v
->value
.size
== 0)
1777 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1781 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
1784 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1785 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1786 void tpm2_sort_pcr_values(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1787 typesafe_qsort(pcr_values
, n_pcr_values
, cmp_pcr_values
);
1790 int tpm2_pcr_values_from_mask(uint32_t mask
, TPMI_ALG_HASH hash
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1791 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1792 size_t n_pcr_values
= 0;
1794 assert(ret_pcr_values
);
1795 assert(ret_n_pcr_values
);
1797 FOREACH_PCR_IN_MASK(index
, mask
)
1798 if (!GREEDY_REALLOC_APPEND(
1801 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1803 return log_oom_debug();
1805 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1806 *ret_n_pcr_values
= n_pcr_values
;
1811 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1814 assert(pcr_values
|| n_pcr_values
== 0);
1817 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1818 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1820 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1821 if (v
->hash
== hash
)
1822 SET_BIT(mask
, v
->index
);
1829 int tpm2_tpml_pcr_selection_from_pcr_values(
1830 const Tpm2PCRValue
*pcr_values
,
1831 size_t n_pcr_values
,
1832 TPML_PCR_SELECTION
*ret_selection
,
1833 TPM2B_DIGEST
**ret_values
,
1834 size_t *ret_n_values
) {
1836 TPML_PCR_SELECTION selection
= {};
1837 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1838 size_t n_values
= 0;
1840 assert(pcr_values
|| n_pcr_values
== 0);
1842 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1843 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR values are not valid.");
1845 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1846 tpm2_tpml_pcr_selection_add_mask(&selection
, v
->hash
, INDEX_TO_MASK(uint32_t, v
->index
));
1848 if (!GREEDY_REALLOC_APPEND(values
, n_values
, &v
->value
, 1))
1849 return log_oom_debug();
1853 *ret_selection
= selection
;
1855 *ret_values
= TAKE_PTR(values
);
1857 *ret_n_values
= n_values
;
1862 /* Count the number of different hash algorithms for all the entries. */
1863 int tpm2_pcr_values_hash_count(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, size_t *ret_count
) {
1864 TPML_PCR_SELECTION selection
;
1870 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1874 /* ret_values= */ NULL
,
1875 /* ret_n_values= */ NULL
);
1879 *ret_count
= selection
.count
;
1884 /* Parse a string argument into a Tpm2PCRValue object.
1886 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1887 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1888 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1889 int tpm2_pcr_value_from_string(const char *arg
, Tpm2PCRValue
*ret_pcr_value
) {
1890 Tpm2PCRValue pcr_value
= {};
1891 const char *p
= arg
;
1895 assert(ret_pcr_value
);
1897 _cleanup_free_
char *index
= NULL
;
1898 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1900 return log_debug_errno(r
, "Could not parse pcr value '%s': %m", p
);
1902 r
= tpm2_pcr_index_from_string(index
);
1904 return log_debug_errno(r
, "Invalid pcr index '%s': %m", index
);
1905 pcr_value
.index
= (unsigned) r
;
1908 _cleanup_free_
char *hash
= NULL
;
1909 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1911 return log_debug_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1913 r
= tpm2_hash_alg_from_string(hash
);
1915 return log_debug_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1916 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1919 /* Remove leading 0x if present */
1920 p
= startswith_no_case(p
, "0x") ?: p
;
1922 _cleanup_free_
void *buf
= NULL
;
1923 size_t buf_size
= 0;
1924 r
= unhexmem(p
, &buf
, &buf_size
);
1926 return log_debug_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1928 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1930 return log_debug_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1932 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1936 *ret_pcr_value
= pcr_value
;
1941 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1942 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1943 * string. This does not check for validity. */
1944 char *tpm2_pcr_value_to_string(const Tpm2PCRValue
*pcr_value
) {
1945 _cleanup_free_
char *index
= NULL
, *value
= NULL
;
1947 if (asprintf(&index
, "%u", pcr_value
->index
) < 0)
1950 const char *hash
= pcr_value
->hash
> 0 ? tpm2_hash_alg_to_string(pcr_value
->hash
) : NULL
;
1952 if (hash
&& pcr_value
->value
.size
> 0) {
1953 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1958 return strjoin(index
, hash
? ":" : "", strempty(hash
), value
? "=" : "", strempty(value
));
1961 /* Parse a string argument into an array of Tpm2PCRValue objects.
1963 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1964 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1965 int tpm2_pcr_values_from_string(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1966 const char *p
= arg
;
1970 assert(ret_pcr_values
);
1971 assert(ret_n_pcr_values
);
1973 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1974 size_t n_pcr_values
= 0;
1977 _cleanup_free_
char *pcr_arg
= NULL
;
1978 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1980 return log_debug_errno(r
, "Could not parse pcr values '%s': %m", p
);
1984 Tpm2PCRValue pcr_value
;
1985 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1989 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1990 return log_oom_debug();
1993 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1994 *ret_n_pcr_values
= n_pcr_values
;
1999 /* Return a string representing the array of PCR values. The format is as described in
2000 * tpm2_pcr_values_from_string(). This does not check for validity. */
2001 char *tpm2_pcr_values_to_string(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2002 _cleanup_free_
char *s
= NULL
;
2004 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2005 _cleanup_free_
char *pcrstr
= tpm2_pcr_value_to_string(v
);
2006 if (!pcrstr
|| !strextend_with_separator(&s
, "+", pcrstr
))
2010 return s
? TAKE_PTR(s
) : strdup("");
2013 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
2014 if (!DEBUG_LOGGING
|| !l
)
2017 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
2018 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
2021 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
2022 if (!DEBUG_LOGGING
|| !pcr_value
)
2025 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
2026 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
2029 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
2030 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
2033 _cleanup_free_
char *h
= hexmem(buffer
, size
);
2034 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
2037 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
2039 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
2042 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
2044 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
2047 static int tpm2_get_policy_digest(
2049 const Tpm2Handle
*session
,
2050 TPM2B_DIGEST
**ret_policy_digest
) {
2054 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
2060 log_debug("Acquiring policy digest.");
2062 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
2063 rc
= sym_Esys_PolicyGetDigest(
2065 session
->esys_handle
,
2070 if (rc
!= TSS2_RC_SUCCESS
)
2071 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2072 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc
));
2074 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
2076 if (ret_policy_digest
)
2077 *ret_policy_digest
= TAKE_PTR(policy_digest
);
2082 int tpm2_create_primary(
2084 const Tpm2Handle
*session
,
2085 const TPM2B_PUBLIC
*template,
2086 const TPM2B_SENSITIVE_CREATE
*sensitive
,
2087 TPM2B_PUBLIC
**ret_public
,
2088 Tpm2Handle
**ret_handle
) {
2097 log_debug("Creating primary key on TPM.");
2099 ts
= now(CLOCK_MONOTONIC
);
2101 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2102 r
= tpm2_handle_new(c
, &handle
);
2106 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2107 rc
= sym_Esys_CreatePrimary(
2110 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2113 sensitive
?: &(TPM2B_SENSITIVE_CREATE
) {},
2115 /* outsideInfo= */ NULL
,
2116 &(TPML_PCR_SELECTION
) {},
2117 &handle
->esys_handle
,
2119 /* creationData= */ NULL
,
2120 /* creationHash= */ NULL
,
2121 /* creationTicket= */ NULL
);
2122 if (rc
!= TSS2_RC_SUCCESS
)
2123 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2124 "Failed to generate primary key in TPM: %s",
2125 sym_Tss2_RC_Decode(rc
));
2127 log_debug("Successfully created primary key on TPM in %s.",
2128 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2131 *ret_public
= TAKE_PTR(public);
2133 *ret_handle
= TAKE_PTR(handle
);
2138 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2139 * instead use tpm2_create_primary(). */
2140 int tpm2_create(Tpm2Context
*c
,
2141 const Tpm2Handle
*parent
,
2142 const Tpm2Handle
*session
,
2143 const TPMT_PUBLIC
*template,
2144 const TPMS_SENSITIVE_CREATE
*sensitive
,
2145 TPM2B_PUBLIC
**ret_public
,
2146 TPM2B_PRIVATE
**ret_private
) {
2155 log_debug("Creating object on TPM.");
2157 ts
= now(CLOCK_MONOTONIC
);
2159 TPM2B_PUBLIC tpm2b_public
= {
2160 .size
= sizeof(*template) - sizeof(template->unique
),
2161 .publicArea
= *template,
2164 /* Zero the unique area. */
2165 zero(tpm2b_public
.publicArea
.unique
);
2167 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2169 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2170 .size
= sizeof(*sensitive
),
2171 .sensitive
= *sensitive
,
2174 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2176 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2177 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2178 rc
= sym_Esys_Create(
2180 parent
->esys_handle
,
2181 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2186 /* outsideInfo= */ NULL
,
2187 &(TPML_PCR_SELECTION
) {},
2190 /* creationData= */ NULL
,
2191 /* creationHash= */ NULL
,
2192 /* creationTicket= */ NULL
);
2193 if (rc
!= TSS2_RC_SUCCESS
)
2194 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2195 "Failed to generate object in TPM: %s",
2196 sym_Tss2_RC_Decode(rc
));
2198 log_debug("Successfully created object on TPM in %s.",
2199 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2202 *ret_public
= TAKE_PTR(public);
2204 *ret_private
= TAKE_PTR(private);
2211 const Tpm2Handle
*parent
,
2212 const Tpm2Handle
*session
,
2213 const TPM2B_PUBLIC
*public,
2214 const TPM2B_PRIVATE
*private,
2215 Tpm2Handle
**ret_handle
) {
2225 log_debug("Loading object into TPM.");
2227 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2228 r
= tpm2_handle_new(c
, &handle
);
2234 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2235 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2240 &handle
->esys_handle
);
2241 if (rc
== TPM2_RC_LOCKOUT
)
2242 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK
),
2243 "TPM2 device is in dictionary attack lockout mode.");
2244 if (rc
!= TSS2_RC_SUCCESS
)
2245 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2246 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2248 *ret_handle
= TAKE_PTR(handle
);
2253 static int tpm2_load_external(
2255 const Tpm2Handle
*session
,
2256 const TPM2B_PUBLIC
*public,
2257 const TPM2B_SENSITIVE
*private,
2258 Tpm2Handle
**ret_handle
) {
2266 log_debug("Loading external key into TPM.");
2268 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2269 r
= tpm2_handle_new(c
, &handle
);
2273 rc
= sym_Esys_LoadExternal(
2275 session
? session
->esys_handle
: ESYS_TR_NONE
,
2281 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2282 * hierarchy, older versions need TPM2_RH_* instead. */
2283 private ? ESYS_TR_RH_NULL
: ESYS_TR_RH_OWNER
,
2285 private ? TPM2_RH_NULL
: TPM2_RH_OWNER
,
2287 &handle
->esys_handle
);
2288 if (rc
!= TSS2_RC_SUCCESS
)
2289 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2290 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2292 *ret_handle
= TAKE_PTR(handle
);
2297 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2298 * use tpm2_create_loaded(). */
2299 static int _tpm2_create_loaded(
2301 const Tpm2Handle
*parent
,
2302 const Tpm2Handle
*session
,
2303 const TPMT_PUBLIC
*template,
2304 const TPMS_SENSITIVE_CREATE
*sensitive
,
2305 TPM2B_PUBLIC
**ret_public
,
2306 TPM2B_PRIVATE
**ret_private
,
2307 Tpm2Handle
**ret_handle
) {
2317 log_debug("Creating loaded object on TPM.");
2319 ts
= now(CLOCK_MONOTONIC
);
2321 /* Copy the input template and zero the unique area. */
2322 TPMT_PUBLIC template_copy
= *template;
2323 zero(template_copy
.unique
);
2325 TPM2B_TEMPLATE tpm2b_template
;
2327 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2329 tpm2b_template
.buffer
,
2330 sizeof(tpm2b_template
.buffer
),
2332 if (rc
!= TSS2_RC_SUCCESS
)
2333 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2334 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc
));
2335 assert(size
<= UINT16_MAX
);
2336 tpm2b_template
.size
= size
;
2338 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2340 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2341 .size
= sizeof(*sensitive
),
2342 .sensitive
= *sensitive
,
2345 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2347 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2348 r
= tpm2_handle_new(c
, &handle
);
2352 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2353 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2354 rc
= sym_Esys_CreateLoaded(
2356 parent
->esys_handle
,
2357 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2362 &handle
->esys_handle
,
2365 if (rc
!= TSS2_RC_SUCCESS
)
2366 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2367 "Failed to generate loaded object in TPM: %s",
2368 sym_Tss2_RC_Decode(rc
));
2370 log_debug("Successfully created loaded object on TPM in %s.",
2371 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2374 *ret_public
= TAKE_PTR(public);
2376 *ret_private
= TAKE_PTR(private);
2378 *ret_handle
= TAKE_PTR(handle
);
2383 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2384 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2385 * tpm2_create_primary(). */
2386 int tpm2_create_loaded(
2388 const Tpm2Handle
*parent
,
2389 const Tpm2Handle
*session
,
2390 const TPMT_PUBLIC
*template,
2391 const TPMS_SENSITIVE_CREATE
*sensitive
,
2392 TPM2B_PUBLIC
**ret_public
,
2393 TPM2B_PRIVATE
**ret_private
,
2394 Tpm2Handle
**ret_handle
) {
2398 if (tpm2_supports_command(c
, TPM2_CC_CreateLoaded
))
2399 return _tpm2_create_loaded(c
, parent
, session
, template, sensitive
, ret_public
, ret_private
, ret_handle
);
2401 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2402 * create and load manually. */
2403 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2404 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2405 r
= tpm2_create(c
, parent
, session
, template, sensitive
, &public, &private);
2409 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2410 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2415 *ret_public
= TAKE_PTR(public);
2417 *ret_private
= TAKE_PTR(private);
2419 *ret_handle
= TAKE_PTR(handle
);
2424 static int tpm2_marshal_private(const TPM2B_PRIVATE
*private, void **ret
, size_t *ret_size
) {
2425 size_t max_size
= sizeof(*private), blob_size
= 0;
2426 _cleanup_free_
void *blob
= NULL
;
2433 blob
= malloc0(max_size
);
2435 return log_oom_debug();
2437 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
2438 if (rc
!= TSS2_RC_SUCCESS
)
2439 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2440 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
2442 *ret
= TAKE_PTR(blob
);
2443 *ret_size
= blob_size
;
2447 static int tpm2_unmarshal_private(const void *data
, size_t size
, TPM2B_PRIVATE
*ret_private
) {
2448 TPM2B_PRIVATE
private = {};
2452 assert(data
|| size
== 0);
2453 assert(ret_private
);
2455 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(data
, size
, &offset
, &private);
2456 if (rc
!= TSS2_RC_SUCCESS
)
2457 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2458 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
2460 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2461 "Garbage at end of private key marshal data.");
2463 *ret_private
= private;
2467 int tpm2_marshal_public(const TPM2B_PUBLIC
*public, void **ret
, size_t *ret_size
) {
2468 size_t max_size
= sizeof(*public), blob_size
= 0;
2469 _cleanup_free_
void *blob
= NULL
;
2476 blob
= malloc0(max_size
);
2478 return log_oom_debug();
2480 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
2481 if (rc
!= TSS2_RC_SUCCESS
)
2482 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2483 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
2485 *ret
= TAKE_PTR(blob
);
2486 *ret_size
= blob_size
;
2490 static int tpm2_unmarshal_public(const void *data
, size_t size
, TPM2B_PUBLIC
*ret_public
) {
2491 TPM2B_PUBLIC
public = {};
2495 assert(data
|| size
== 0);
2498 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(data
, size
, &offset
, &public);
2499 if (rc
!= TSS2_RC_SUCCESS
)
2500 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2501 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
2503 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2504 "Garbage at end of public key marshal data.");
2506 *ret_public
= public;
2510 int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC
*nv_public
, void **ret
, size_t *ret_size
) {
2511 size_t max_size
= sizeof(*nv_public
), blob_size
= 0;
2512 _cleanup_free_
void *blob
= NULL
;
2519 blob
= malloc0(max_size
);
2521 return log_oom_debug();
2523 rc
= sym_Tss2_MU_TPM2B_NV_PUBLIC_Marshal(nv_public
, blob
, max_size
, &blob_size
);
2524 if (rc
!= TSS2_RC_SUCCESS
)
2525 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2526 "Failed to marshal NV public structure: %s", sym_Tss2_RC_Decode(rc
));
2528 *ret
= TAKE_PTR(blob
);
2529 *ret_size
= blob_size
;
2533 int tpm2_unmarshal_nv_public(const void *data
, size_t size
, TPM2B_NV_PUBLIC
*ret_nv_public
) {
2534 TPM2B_NV_PUBLIC nv_public
= {};
2538 assert(data
|| size
== 0);
2539 assert(ret_nv_public
);
2541 rc
= sym_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal(data
, size
, &offset
, &nv_public
);
2542 if (rc
!= TSS2_RC_SUCCESS
)
2543 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2544 "Failed to unmarshal NV public structure: %s", sym_Tss2_RC_Decode(rc
));
2546 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2547 "Garbage at end of NV public structure marshal data.");
2549 *ret_nv_public
= nv_public
;
2553 static int tpm2_import(
2555 const Tpm2Handle
*parent
,
2556 const Tpm2Handle
*session
,
2557 const TPM2B_PUBLIC
*public,
2558 const TPM2B_PRIVATE
*private,
2559 const TPM2B_ENCRYPTED_SECRET
*seed
,
2560 const TPM2B_DATA
*encryption_key
,
2561 const TPMT_SYM_DEF_OBJECT
*symmetric
,
2562 TPM2B_PRIVATE
**ret_private
) {
2568 assert(!!encryption_key
== !!symmetric
);
2572 assert(ret_private
);
2574 log_debug("Importing key into TPM.");
2576 rc
= sym_Esys_Import(
2578 parent
->esys_handle
,
2579 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2586 symmetric
?: &(TPMT_SYM_DEF_OBJECT
){ .algorithm
= TPM2_ALG_NULL
, },
2588 if (rc
!= TSS2_RC_SUCCESS
)
2589 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2590 "Failed to import key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2595 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2596 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2597 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2598 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2602 const TPML_PCR_SELECTION
*pcr_selection
,
2603 Tpm2PCRValue
**ret_pcr_values
,
2604 size_t *ret_n_pcr_values
) {
2606 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2607 size_t n_pcr_values
= 0;
2611 assert(pcr_selection
);
2612 assert(ret_pcr_values
);
2613 assert(ret_n_pcr_values
);
2615 TPML_PCR_SELECTION remaining
= *pcr_selection
;
2616 while (!tpm2_tpml_pcr_selection_is_empty(&remaining
)) {
2617 _cleanup_(Esys_Freep
) TPML_PCR_SELECTION
*current_read
= NULL
;
2618 _cleanup_(Esys_Freep
) TPML_DIGEST
*current_values
= NULL
;
2620 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2622 /* Unfortunately, PCR_Read will not return more than 8 values. */
2623 rc
= sym_Esys_PCR_Read(
2632 if (rc
!= TSS2_RC_SUCCESS
)
2633 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2634 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc
));
2636 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2638 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2639 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2644 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2645 assert(i
< current_values
->count
);
2646 Tpm2PCRValue pcr_value
= {
2649 .value
= current_values
->digests
[i
++],
2652 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2654 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2655 return log_oom_debug();
2657 assert(i
== current_values
->count
);
2659 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2662 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
2664 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
2665 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "PCR values read from TPM are not valid.");
2667 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2668 *ret_n_pcr_values
= n_pcr_values
;
2673 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2674 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2675 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2676 * appropriate entries, this returns an error. This does not check the array for validity. */
2677 int tpm2_pcr_read_missing_values(Tpm2Context
*c
, Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2678 TPMI_ALG_HASH pcr_bank
= 0;
2682 assert(pcr_values
|| n_pcr_values
== 0);
2684 if (n_pcr_values
> 0) {
2686 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2688 return log_debug_errno(r
, "Could not get hash count from pcr values: %m");
2690 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2692 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2696 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2702 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2706 if (v
->value
.size
> 0)
2709 TPML_PCR_SELECTION selection
;
2710 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
2714 _cleanup_free_ Tpm2PCRValue
*read_values
= NULL
;
2715 size_t n_read_values
;
2716 r
= tpm2_pcr_read(c
, &selection
, &read_values
, &n_read_values
);
2720 if (n_read_values
== 0)
2721 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2722 "Could not read PCR hash 0x%" PRIu16
" index %u",
2725 assert(n_read_values
== 1);
2726 assert(read_values
[0].hash
== v
->hash
);
2727 assert(read_values
[0].index
== v
->index
);
2729 v
->value
= read_values
[0].value
;
2735 static int tpm2_pcr_mask_good(
2740 TPML_PCR_SELECTION selection
;
2745 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2746 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2747 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2749 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
2751 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2752 size_t n_pcr_values
;
2753 r
= tpm2_pcr_read(c
, &selection
, &pcr_values
, &n_pcr_values
);
2757 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2758 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
2759 if (!memeqbyte(0x00, v
->value
.buffer
, v
->value
.size
) &&
2760 !memeqbyte(0xFF, v
->value
.buffer
, v
->value
.size
))
2766 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
2770 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2771 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2772 if (selection
->sizeofSelect
< TPM2_PCRS_MAX
/8) {
2773 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2774 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2778 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
2780 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2781 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2783 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2784 if (selection
->pcrSelect
[j
] != 0xFF) {
2790 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2791 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2796 int tpm2_get_best_pcr_bank(
2799 TPMI_ALG_HASH
*ret
) {
2801 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
2807 if (pcr_mask
== 0) {
2808 log_debug("Asked to pick best PCR bank but no PCRs selected we could derive this from. Defaulting to SHA256.");
2809 *ret
= TPM2_ALG_SHA256
; /* if no PCRs are selected this doesn't matter anyway... */
2813 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2814 TPMI_ALG_HASH hash
= selection
->hash
;
2817 /* For now we are only interested in the SHA1 and SHA256 banks */
2818 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2821 r
= tpm2_bank_has24(selection
);
2827 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2831 if (hash
== TPM2_ALG_SHA256
) {
2832 supported_hash
= TPM2_ALG_SHA256
;
2834 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2835 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2839 assert(hash
== TPM2_ALG_SHA1
);
2841 if (supported_hash
== 0)
2842 supported_hash
= TPM2_ALG_SHA1
;
2844 if (good
&& hash_with_valid_pcr
== 0)
2845 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
2849 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2850 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2853 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2854 * not initialized. */
2856 if (hash_with_valid_pcr
== TPM2_ALG_SHA256
) {
2857 assert(supported_hash
== TPM2_ALG_SHA256
);
2858 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2859 *ret
= TPM2_ALG_SHA256
;
2860 } else if (hash_with_valid_pcr
== TPM2_ALG_SHA1
) {
2861 if (supported_hash
== TPM2_ALG_SHA256
)
2862 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.");
2864 assert(supported_hash
== TPM2_ALG_SHA1
);
2865 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.");
2868 *ret
= TPM2_ALG_SHA1
;
2869 } else if (supported_hash
== TPM2_ALG_SHA256
) {
2870 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!");
2871 *ret
= TPM2_ALG_SHA256
;
2872 } else if (supported_hash
== TPM2_ALG_SHA1
) {
2873 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!");
2874 *ret
= TPM2_ALG_SHA1
;
2876 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2877 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2882 int tpm2_get_good_pcr_banks(
2885 TPMI_ALG_HASH
**ret
) {
2887 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2888 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2894 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2895 TPMI_ALG_HASH hash
= selection
->hash
;
2897 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2898 r
= tpm2_bank_has24(selection
);
2904 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2905 r
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2909 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2910 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2913 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2914 return log_oom_debug();
2916 good_banks
[n_good_banks
++] = hash
;
2918 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2919 return log_oom_debug();
2921 fallback_banks
[n_fallback_banks
++] = hash
;
2925 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2926 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2927 if (n_good_banks
> 0) {
2928 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks
);
2929 *ret
= TAKE_PTR(good_banks
);
2930 return (int) n_good_banks
;
2932 if (n_fallback_banks
> 0) {
2933 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks
);
2934 *ret
= TAKE_PTR(fallback_banks
);
2935 return (int) n_fallback_banks
;
2938 /* No suitable banks found. */
2943 int tpm2_get_good_pcr_banks_strv(
2949 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2950 _cleanup_strv_free_
char **l
= NULL
;
2956 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2960 FOREACH_ARRAY(a
, algs
, n_algs
) {
2961 _cleanup_free_
char *n
= NULL
;
2962 const EVP_MD
*implementation
;
2965 salg
= tpm2_hash_alg_to_string(*a
);
2967 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
2969 implementation
= EVP_get_digestbyname(salg
);
2970 if (!implementation
)
2971 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2973 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2975 return log_oom_debug();
2977 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2979 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2980 return log_oom_debug();
2985 #else /* HAVE_OPENSSL */
2986 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2990 /* Hash data into the digest.
2992 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2993 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2994 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2995 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2997 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2998 * correct for 'alg'.
3000 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
3001 int tpm2_digest_many(
3003 TPM2B_DIGEST
*digest
,
3004 const struct iovec data
[],
3008 struct sha256_ctx ctx
;
3011 assert(data
|| n_data
== 0);
3013 if (alg
!= TPM2_ALG_SHA256
)
3014 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3015 "Hash algorithm not supported: 0x%x", alg
);
3017 if (extend
&& digest
->size
!= SHA256_DIGEST_SIZE
)
3018 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3019 "Digest size 0x%x, require 0x%x",
3020 digest
->size
, (unsigned)SHA256_DIGEST_SIZE
);
3022 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
3023 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
3027 sha256_init_ctx(&ctx
);
3030 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
3032 *digest
= (TPM2B_DIGEST
) {
3033 .size
= SHA256_DIGEST_SIZE
,
3035 if (n_data
== 0) /* If not extending and no data, return zero hash */
3039 FOREACH_ARRAY(d
, data
, n_data
)
3040 sha256_process_bytes(d
->iov_base
, d
->iov_len
, &ctx
);
3042 sha256_finish_ctx(&ctx
, digest
->buffer
);
3047 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
3048 int tpm2_digest_many_digests(
3050 TPM2B_DIGEST
*digest
,
3051 const TPM2B_DIGEST data
[],
3055 _cleanup_free_
struct iovec
*iovecs
= NULL
;
3057 assert(data
|| n_data
== 0);
3059 iovecs
= new(struct iovec
, n_data
);
3061 return log_oom_debug();
3063 for (size_t i
= 0; i
< n_data
; i
++)
3064 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
3066 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
3069 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
3070 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
3071 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
3072 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
3073 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
3075 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
3076 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
3077 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
3078 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
3080 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
3081 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
3082 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
3084 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
3085 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
3086 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
3087 * which we will trim the 0(s) from before sending to the TPM.
3089 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
3090 bool trimmed
= false;
3094 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
3100 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
3103 int tpm2_auth_value_from_pin(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
3104 TPM2B_AUTH auth
= {};
3110 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
3114 tpm2_trim_auth_value(&auth
);
3116 *ret_auth
= TAKE_STRUCT(auth
);
3121 int tpm2_set_auth_binary(Tpm2Context
*c
, const Tpm2Handle
*handle
, const TPM2B_AUTH
*auth
) {
3130 rc
= sym_Esys_TR_SetAuth(c
->esys_context
, handle
->esys_handle
, auth
);
3131 if (rc
!= TSS2_RC_SUCCESS
)
3132 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3133 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc
));
3138 int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
3139 TPM2B_AUTH auth
= {};
3148 CLEANUP_ERASE(auth
);
3150 r
= tpm2_auth_value_from_pin(TPM2_ALG_SHA256
, pin
, &auth
);
3154 return tpm2_set_auth_binary(c
, handle
, &auth
);
3157 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
3158 TPMA_SESSION flags
= 0;
3164 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
3165 if (rc
!= TSS2_RC_SUCCESS
)
3168 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
3171 int tpm2_make_encryption_session(
3173 const Tpm2Handle
*primary
,
3174 const Tpm2Handle
*bind_key
,
3175 Tpm2Handle
**ret_session
) {
3177 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
3178 TPMA_SESSION_CONTINUESESSION
;
3184 assert(ret_session
);
3186 log_debug("Starting HMAC encryption session.");
3188 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
3189 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
3190 * recover the salt, which is then used for key derivation. */
3191 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
3192 r
= tpm2_handle_new(c
, &session
);
3196 rc
= sym_Esys_StartAuthSession(
3198 primary
->esys_handle
,
3199 bind_key
? bind_key
->esys_handle
: ESYS_TR_NONE
,
3205 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
3207 &session
->esys_handle
);
3208 if (rc
!= TSS2_RC_SUCCESS
)
3209 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3210 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
3212 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
3213 * always used for sessions), this provides confidentiality, integrity and replay protection for
3214 * operations that use this session. */
3215 rc
= sym_Esys_TRSess_SetAttributes(c
->esys_context
, session
->esys_handle
, sessionAttributes
, 0xff);
3216 if (rc
!= TSS2_RC_SUCCESS
)
3217 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3218 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc
));
3220 *ret_session
= TAKE_PTR(session
);
3225 int tpm2_make_policy_session(
3227 const Tpm2Handle
*primary
,
3228 const Tpm2Handle
*encryption_session
,
3229 Tpm2Handle
**ret_session
) {
3236 assert(encryption_session
);
3237 assert(ret_session
);
3239 if (!tpm2_is_encryption_session(c
, encryption_session
))
3240 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
3241 "Missing encryption session");
3243 log_debug("Starting policy session.");
3245 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
3246 r
= tpm2_handle_new(c
, &session
);
3250 rc
= sym_Esys_StartAuthSession(
3252 primary
->esys_handle
,
3254 encryption_session
->esys_handle
,
3259 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
3261 &session
->esys_handle
);
3262 if (rc
!= TSS2_RC_SUCCESS
)
3263 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3264 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
3266 *ret_session
= TAKE_PTR(session
);
3271 static int find_signature(
3273 const TPML_PCR_SELECTION
*pcr_selection
,
3278 void *ret_signature
,
3279 size_t *ret_signature_size
) {
3286 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3287 * public key, and policy digest. */
3289 if (!json_variant_is_object(v
))
3290 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
3292 uint16_t pcr_bank
= pcr_selection
->pcrSelections
[0].hash
;
3293 uint32_t pcr_mask
= tpm2_tpml_pcr_selection_to_mask(pcr_selection
, pcr_bank
);
3295 k
= tpm2_hash_alg_to_string(pcr_bank
);
3297 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
3299 /* First, find field by bank */
3300 b
= json_variant_by_key(v
, k
);
3302 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
3304 if (!json_variant_is_array(b
))
3305 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
3307 /* Now iterate through all signatures known for this bank */
3308 JSON_VARIANT_ARRAY_FOREACH(i
, b
) {
3309 _cleanup_free_
void *fpj_data
= NULL
, *polj_data
= NULL
;
3310 JsonVariant
*maskj
, *fpj
, *sigj
, *polj
;
3311 size_t fpj_size
, polj_size
;
3312 uint32_t parsed_mask
;
3314 if (!json_variant_is_object(i
))
3315 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
3317 /* Check if the PCR mask matches our expectations */
3318 maskj
= json_variant_by_key(i
, "pcrs");
3322 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
3324 return log_debug_errno(r
, "Failed to parse JSON PCR mask");
3326 if (parsed_mask
!= pcr_mask
)
3327 continue; /* Not for this PCR mask */
3329 /* Then check if this is for the public key we operate with */
3330 fpj
= json_variant_by_key(i
, "pkfp");
3334 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
3336 return log_debug_errno(r
, "Failed to decode fingerprint in JSON data: %m");
3338 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
3339 continue; /* Not for this public key */
3341 /* Finally, check if this is for the PCR policy we expect this to be */
3342 polj
= json_variant_by_key(i
, "pol");
3346 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
3348 return log_debug_errno(r
, "Failed to decode policy hash JSON data: %m");
3350 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
3353 /* This entry matches all our expectations, now return the signature included in it */
3354 sigj
= json_variant_by_key(i
, "sig");
3358 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
3361 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Couldn't find signature for this PCR bank, PCR index and public key.");
3362 #else /* HAVE_OPENSSL */
3363 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3367 /* Calculates the "name" of a public key.
3369 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3370 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3371 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3372 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3373 * that would also change the key name.
3375 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3376 * nameAlg is not TPM2_ALG_SHA256. */
3377 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC
*public, TPM2B_NAME
*ret_name
) {
3386 return log_debug_errno(r
, "TPM2 support not installed: %m");
3388 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3389 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3390 "Unsupported nameAlg: 0x%x",
3393 _cleanup_free_
uint8_t *buf
= NULL
;
3396 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3398 return log_oom_debug();
3400 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf
, sizeof(TPMT_PUBLIC
), &size
);
3401 if (rc
!= TSS2_RC_SUCCESS
)
3402 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3403 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3405 TPM2B_DIGEST digest
= {};
3406 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3411 .hashAlg
= TPM2_ALG_SHA256
,
3413 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3414 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3418 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3419 if (rc
!= TSS2_RC_SUCCESS
)
3420 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3421 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc
));
3424 tpm2_log_debug_name(&name
, "Calculated public key name");
3431 /* Get the "name" of a key from the TPM.
3433 * The "name" of a key is explained above in tpm2_calculate_pubkey_name().
3435 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3436 * public/private keypair. */
3439 const Tpm2Handle
*handle
,
3440 TPM2B_NAME
**ret_name
) {
3442 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
3449 rc
= sym_Esys_TR_GetName(c
->esys_context
, handle
->esys_handle
, &name
);
3450 if (rc
!= TSS2_RC_SUCCESS
)
3451 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3452 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc
));
3454 tpm2_log_debug_name(name
, "Object name");
3456 *ret_name
= TAKE_PTR(name
);
3461 int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC
*nvpublic
, TPM2B_NAME
*ret_name
) {
3470 return log_debug_errno(r
, "TPM2 support not installed: %m");
3472 if (nvpublic
->nameAlg
!= TPM2_ALG_SHA256
)
3473 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3474 "Unsupported nameAlg: 0x%x",
3477 _cleanup_free_
uint8_t *buf
= NULL
;
3480 buf
= (uint8_t*) new(TPMS_NV_PUBLIC
, 1);
3482 return log_oom_debug();
3484 rc
= sym_Tss2_MU_TPMS_NV_PUBLIC_Marshal(nvpublic
, buf
, sizeof(TPMS_NV_PUBLIC
), &size
);
3485 if (rc
!= TSS2_RC_SUCCESS
)
3486 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3487 "Failed to marshal NV index: %s", sym_Tss2_RC_Decode(rc
));
3489 TPM2B_DIGEST digest
= {};
3490 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3495 .hashAlg
= TPM2_ALG_SHA256
,
3497 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3498 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3502 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3503 if (rc
!= TSS2_RC_SUCCESS
)
3504 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3505 "Failed to marshal NV index name: %s", sym_Tss2_RC_Decode(rc
));
3508 tpm2_log_debug_name(&name
, "Calculated NV index name");
3515 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3516 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST
*digest
) {
3517 TPM2_CC command
= TPM2_CC_PolicyAuthValue
;
3522 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3526 return log_debug_errno(r
, "TPM2 support not installed: %m");
3528 uint8_t buf
[sizeof(command
)];
3531 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3532 if (rc
!= TSS2_RC_SUCCESS
)
3533 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3534 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc
));
3536 if (offset
!= sizeof(command
))
3537 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3538 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3540 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3544 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3549 int tpm2_policy_auth_value(
3551 const Tpm2Handle
*session
,
3552 TPM2B_DIGEST
**ret_policy_digest
) {
3559 log_debug("Submitting AuthValue policy.");
3561 rc
= sym_Esys_PolicyAuthValue(
3563 session
->esys_handle
,
3567 if (rc
!= TSS2_RC_SUCCESS
)
3568 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3569 "Failed to add authValue policy to TPM: %s",
3570 sym_Tss2_RC_Decode(rc
));
3572 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3575 /* Extend 'digest' with the PolicySigned calculated hash. */
3576 int tpm2_calculate_policy_signed(TPM2B_DIGEST
*digest
, const TPM2B_NAME
*name
) {
3577 TPM2_CC command
= TPM2_CC_PolicySigned
;
3582 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3587 return log_debug_errno(r
, "TPM2 support not installed: %m");
3589 uint8_t buf
[sizeof(command
)];
3592 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3593 if (rc
!= TSS2_RC_SUCCESS
)
3594 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3595 "Failed to marshal PolicySigned command: %s", sym_Tss2_RC_Decode(rc
));
3597 if (offset
!= sizeof(command
))
3598 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3599 "Offset 0x%zx wrong after marshalling PolicySigned command", offset
);
3601 struct iovec data
[] = {
3602 IOVEC_MAKE(buf
, offset
),
3603 IOVEC_MAKE(name
->name
, name
->size
),
3606 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3610 const TPM2B_NONCE policyRef
= {}; /* For now, we do not make use of the policyRef stuff */
3612 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, policyRef
.buffer
, policyRef
.size
, /* extend= */ true);
3616 tpm2_log_debug_digest(digest
, "PolicySigned calculated digest");
3621 int tpm2_policy_signed_hmac_sha256(
3623 const Tpm2Handle
*session
,
3624 const Tpm2Handle
*hmac_key_handle
,
3625 const struct iovec
*hmac_key
,
3626 TPM2B_DIGEST
**ret_policy_digest
) {
3634 assert(hmac_key_handle
);
3635 assert(iovec_is_set(hmac_key
));
3637 /* This sends a TPM2_PolicySigned command to the tpm. As signature key we use an HMAC-SHA256 key
3638 * specified in the hmac_key parameter. The secret key must be loaded into the TPM already and
3639 * referenced in hmac_key_handle. */
3641 log_debug("Submitting PolicySigned policy for HMAC-SHA256.");
3643 /* Acquire the nonce from the TPM that we shall sign */
3644 _cleanup_(Esys_Freep
) TPM2B_NONCE
*nonce
= NULL
;
3645 rc
= sym_Esys_TRSess_GetNonceTPM(
3647 session
->esys_handle
,
3649 if (rc
!= TSS2_RC_SUCCESS
)
3650 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3651 "Failed to determine NoneTPM of auth session: %s",
3652 sym_Tss2_RC_Decode(rc
));
3654 be32_t expiration
= htobe64(0);
3655 const TPM2B_DIGEST cpHashA
= {}; /* For now, we do not make use of the cpHashA stuff */
3656 const TPM2B_NONCE policyRef
= {}; /* ditto, we do not bother with policyRef */
3658 /* Put together the data to sign, as per TPM2 Spec Part 3, 23.3.1 */
3659 struct iovec data_to_sign
[] = {
3660 IOVEC_MAKE(nonce
->buffer
, nonce
->size
),
3661 IOVEC_MAKE(&expiration
, sizeof(expiration
)),
3662 IOVEC_MAKE(cpHashA
.buffer
, cpHashA
.size
),
3663 IOVEC_MAKE(policyRef
.buffer
, policyRef
.size
),
3666 /* Now calculate the digest of the data we put together */
3667 TPM2B_DIGEST digest_to_sign
;
3668 r
= tpm2_digest_many(TPM2_ALG_SHA256
, &digest_to_sign
, data_to_sign
, ELEMENTSOF(data_to_sign
), /* extend= */ false);
3672 unsigned char hmac_signature
[SHA256_DIGEST_SIZE
];
3673 unsigned hmac_signature_size
= sizeof(hmac_signature
);
3675 /* And sign this with our key */
3676 if (!HMAC(EVP_sha256(),
3679 digest_to_sign
.buffer
,
3680 digest_to_sign
.size
,
3682 &hmac_signature_size
))
3683 return -ENOTRECOVERABLE
;
3685 /* Now bring the signature into a format that the TPM understands */
3686 TPMT_SIGNATURE sig
= {
3687 .sigAlg
= TPM2_ALG_HMAC
,
3688 .signature
.hmac
.hashAlg
= TPM2_ALG_SHA256
,
3690 assert(hmac_signature_size
== sizeof(sig
.signature
.hmac
.digest
.sha256
));
3691 memcpy(sig
.signature
.hmac
.digest
.sha256
, hmac_signature
, hmac_signature_size
);
3693 /* And submit the whole shebang to the TPM */
3694 rc
= sym_Esys_PolicySigned(
3696 hmac_key_handle
->esys_handle
,
3697 session
->esys_handle
,
3698 /* shandle1= */ ESYS_TR_NONE
,
3699 /* shandle2= */ ESYS_TR_NONE
,
3700 /* shandle3= */ ESYS_TR_NONE
,
3706 /* timeout= */ NULL
,
3707 /* policyTicket= */ NULL
);
3708 if (rc
!= TSS2_RC_SUCCESS
)
3709 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3710 "Failed to add PolicySigned policy to TPM: %s",
3711 sym_Tss2_RC_Decode(rc
));
3713 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3714 #else /* HAVE_OPENSSL */
3715 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3719 int tpm2_calculate_policy_authorize_nv(
3720 const TPM2B_NV_PUBLIC
*public_info
,
3721 TPM2B_DIGEST
*digest
) {
3722 TPM2_CC command
= TPM2_CC_PolicyAuthorizeNV
;
3726 assert(public_info
);
3728 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3732 return log_debug_errno(r
, "TPM2 support not installed: %m");
3734 uint8_t buf
[sizeof(command
)];
3737 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3738 if (rc
!= TSS2_RC_SUCCESS
)
3739 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3740 "Failed to marshal PolicyAuthorizeNV command: %s", sym_Tss2_RC_Decode(rc
));
3742 if (offset
!= sizeof(command
))
3743 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3744 "Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset
);
3746 TPM2B_NV_PUBLIC public_info_copy
= *public_info
; /* Make a copy, since we must set TPMA_NV_WRITTEN for the calculation */
3747 public_info_copy
.nvPublic
.attributes
|= TPMA_NV_WRITTEN
;
3749 TPM2B_NAME name
= {};
3750 r
= tpm2_calculate_nv_index_name(&public_info_copy
.nvPublic
, &name
);
3754 struct iovec data
[] = {
3755 IOVEC_MAKE(buf
, offset
),
3756 IOVEC_MAKE(name
.name
, name
.size
),
3759 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3763 tpm2_log_debug_digest(digest
, "PolicyAuthorizeNV calculated digest");
3768 int tpm2_policy_authorize_nv(
3770 const Tpm2Handle
*session
,
3771 const Tpm2Handle
*nv_handle
,
3772 TPM2B_DIGEST
**ret_policy_digest
) {
3779 log_debug("Submitting AuthorizeNV policy.");
3781 rc
= sym_Esys_PolicyAuthorizeNV(
3784 nv_handle
->esys_handle
,
3785 session
->esys_handle
,
3789 if (rc
!= TSS2_RC_SUCCESS
)
3790 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3791 "Failed to add AuthorizeNV policy to TPM: %s",
3792 sym_Tss2_RC_Decode(rc
));
3794 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3799 const Tpm2Handle
*session
,
3800 const TPM2B_DIGEST
*branches
, size_t n_branches
,
3801 TPM2B_DIGEST
**ret_policy_digest
) {
3803 TPML_DIGEST hash_list
;
3809 if (n_branches
> ELEMENTSOF(hash_list
.digests
))
3812 log_debug("Submitting OR policy.");
3814 hash_list
= (TPML_DIGEST
) {
3815 .count
= n_branches
,
3818 memcpy(hash_list
.digests
, branches
, n_branches
* sizeof(TPM2B_DIGEST
));
3821 for (size_t i
= 0; i
< hash_list
.count
; i
++) {
3822 _cleanup_free_
char *h
= hexmem(hash_list
.digests
[i
].buffer
, hash_list
.digests
[i
].size
);
3823 log_debug("Submitting OR Branch #%zu: %s", i
, h
);
3826 rc
= sym_Esys_PolicyOR(
3828 session
->esys_handle
,
3833 if (rc
!= TSS2_RC_SUCCESS
)
3834 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3835 "Failed to add OR policy to TPM: %s",
3836 sym_Tss2_RC_Decode(rc
));
3838 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3841 /* Extend 'digest' with the PolicyOR calculated hash. */
3842 int tpm2_calculate_policy_or(const TPM2B_DIGEST
*branches
, size_t n_branches
, TPM2B_DIGEST
*digest
) {
3843 TPM2_CC command
= TPM2_CC_PolicyOR
;
3848 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3850 if (n_branches
== 0)
3852 if (n_branches
== 1)
3853 log_warning("PolicyOR with a single branch submitted, this is weird.");
3859 return log_error_errno(r
, "TPM2 support not installed: %m");
3861 uint8_t buf
[sizeof(command
)];
3864 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3865 if (rc
!= TSS2_RC_SUCCESS
)
3866 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3867 "Failed to marshal PolicyOR command: %s", sym_Tss2_RC_Decode(rc
));
3869 if (offset
!= sizeof(command
))
3870 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3871 "Offset 0x%zx wrong after marshalling PolicyOR command", offset
);
3872 _cleanup_free_
struct iovec
*data
= new(struct iovec
, 1 + n_branches
);
3876 data
[0] = IOVEC_MAKE(buf
, offset
);
3877 for (size_t i
= 0; i
< n_branches
; i
++) {
3878 data
[1 + i
] = IOVEC_MAKE((void*) branches
[i
].buffer
, branches
[i
].size
);
3880 if (DEBUG_LOGGING
) {
3881 _cleanup_free_
char *h
= hexmem(branches
[i
].buffer
, branches
[i
].size
);
3882 log_debug("OR Branch #%zu: %s", i
, h
);
3886 /* PolicyOR does not use the previous hash value; we must zero and then extend it. */
3887 zero(digest
->buffer
);
3889 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, 1 + n_branches
, /* extend= */ true);
3893 tpm2_log_debug_digest(digest
, "PolicyOR calculated digest");
3898 /* Extend 'digest' with the PolicyPCR calculated hash. */
3899 int tpm2_calculate_policy_pcr(
3900 const Tpm2PCRValue
*pcr_values
,
3901 size_t n_pcr_values
,
3902 TPM2B_DIGEST
*digest
) {
3904 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3908 assert(pcr_values
|| n_pcr_values
== 0);
3910 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3914 return log_debug_errno(r
, "TPM2 support not installed: %m");
3916 TPML_PCR_SELECTION pcr_selection
;
3917 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3919 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3921 return log_debug_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3923 TPM2B_DIGEST hash
= {};
3924 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3928 _cleanup_free_
uint8_t *buf
= NULL
;
3929 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3931 buf
= malloc(maxsize
);
3933 return log_oom_debug();
3935 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, maxsize
, &size
);
3936 if (rc
!= TSS2_RC_SUCCESS
)
3937 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3938 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc
));
3940 rc
= sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection
, buf
, maxsize
, &size
);
3941 if (rc
!= TSS2_RC_SUCCESS
)
3942 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3943 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc
));
3945 struct iovec data
[] = {
3946 IOVEC_MAKE(buf
, size
),
3947 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3949 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3953 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3958 int tpm2_policy_pcr(
3960 const Tpm2Handle
*session
,
3961 const TPML_PCR_SELECTION
*pcr_selection
,
3962 TPM2B_DIGEST
**ret_policy_digest
) {
3968 assert(pcr_selection
);
3970 log_debug("Submitting PCR hash policy.");
3972 rc
= sym_Esys_PolicyPCR(
3974 session
->esys_handle
,
3980 if (rc
!= TSS2_RC_SUCCESS
)
3981 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3982 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc
));
3984 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3987 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3988 int tpm2_calculate_policy_authorize(
3989 const TPM2B_PUBLIC
*public,
3990 const TPM2B_DIGEST
*policy_ref
,
3991 TPM2B_DIGEST
*digest
) {
3993 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3999 assert(digest
->size
== SHA256_DIGEST_SIZE
);
4003 return log_debug_errno(r
, "TPM2 support not installed: %m");
4005 uint8_t buf
[sizeof(command
)];
4008 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
4009 if (rc
!= TSS2_RC_SUCCESS
)
4010 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4011 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc
));
4013 if (offset
!= sizeof(command
))
4014 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4015 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
4017 TPM2B_NAME name
= {};
4018 r
= tpm2_calculate_pubkey_name(&public->publicArea
, &name
);
4022 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
4023 zero(digest
->buffer
);
4025 struct iovec data
[] = {
4026 IOVEC_MAKE(buf
, offset
),
4027 IOVEC_MAKE(name
.name
, name
.size
),
4029 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
4033 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
4035 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
4037 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
4041 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
4046 static int tpm2_policy_authorize(
4048 const Tpm2Handle
*session
,
4049 TPML_PCR_SELECTION
*pcr_selection
,
4050 const TPM2B_PUBLIC
*public,
4053 JsonVariant
*signature_json
,
4054 TPM2B_DIGEST
**ret_policy_digest
) {
4061 assert(pcr_selection
);
4063 assert(fp
&& fp_size
> 0);
4065 log_debug("Adding PCR signature policy.");
4067 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
4068 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
4072 /* Acquire the "name" of what we just loaded */
4073 _cleanup_(Esys_Freep
) TPM2B_NAME
*pubkey_name
= NULL
;
4074 r
= tpm2_get_name(c
, pubkey_handle
, &pubkey_name
);
4078 /* If we have a signature, proceed with verifying the PCR digest */
4079 const TPMT_TK_VERIFIED
*check_ticket
;
4080 _cleanup_(Esys_Freep
) TPMT_TK_VERIFIED
*check_ticket_buffer
= NULL
;
4081 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*approved_policy
= NULL
;
4082 if (signature_json
) {
4083 r
= tpm2_policy_pcr(
4091 _cleanup_free_
void *signature_raw
= NULL
;
4092 size_t signature_size
;
4098 approved_policy
->buffer
,
4099 approved_policy
->size
,
4105 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
4106 * hence we need to do the SHA256 part ourselves, first */
4107 TPM2B_DIGEST signature_hash
= *approved_policy
;
4108 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, &signature_hash
);
4112 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
4114 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
4116 TPMT_SIGNATURE policy_signature
= {
4117 .sigAlg
= TPM2_ALG_RSASSA
,
4118 .signature
.rsassa
= {
4119 .hash
= TPM2_ALG_SHA256
,
4120 .sig
= TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw
, signature_size
),
4124 rc
= sym_Esys_VerifySignature(
4126 pubkey_handle
->esys_handle
,
4132 &check_ticket_buffer
);
4133 if (rc
!= TSS2_RC_SUCCESS
)
4134 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4135 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc
));
4137 check_ticket
= check_ticket_buffer
;
4139 /* When enrolling, we pass a NULL ticket */
4140 static const TPMT_TK_VERIFIED check_ticket_null
= {
4141 .tag
= TPM2_ST_VERIFIED
,
4142 .hierarchy
= TPM2_RH_OWNER
,
4145 check_ticket
= &check_ticket_null
;
4148 rc
= sym_Esys_PolicyAuthorize(
4150 session
->esys_handle
,
4155 /* policyRef= */ &(const TPM2B_NONCE
) {},
4158 if (rc
!= TSS2_RC_SUCCESS
)
4159 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4160 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc
));
4162 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
4165 /* Extend 'digest' with the calculated policy hash. */
4166 int tpm2_calculate_sealing_policy(
4167 const Tpm2PCRValue
*pcr_values
,
4168 size_t n_pcr_values
,
4169 const TPM2B_PUBLIC
*public,
4171 const Tpm2PCRLockPolicy
*pcrlock_policy
,
4172 TPM2B_DIGEST
*digest
) {
4176 assert(pcr_values
|| n_pcr_values
== 0);
4179 if (public && pcrlock_policy
)
4180 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Policies with both signed PCR and pcrlock are currently not supported.");
4183 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
4188 if (pcrlock_policy
) {
4189 TPM2B_NV_PUBLIC nv_public
;
4191 r
= tpm2_unmarshal_nv_public(
4192 pcrlock_policy
->nv_public
.iov_base
,
4193 pcrlock_policy
->nv_public
.iov_len
,
4198 r
= tpm2_calculate_policy_authorize_nv(&nv_public
, digest
);
4203 if (n_pcr_values
> 0) {
4204 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
4210 r
= tpm2_calculate_policy_auth_value(digest
);
4218 static int tpm2_build_sealing_policy(
4220 const Tpm2Handle
*session
,
4221 uint32_t hash_pcr_mask
,
4223 const TPM2B_PUBLIC
*public,
4226 uint32_t pubkey_pcr_mask
,
4227 JsonVariant
*signature_json
,
4229 const Tpm2PCRLockPolicy
*pcrlock_policy
,
4230 TPM2B_DIGEST
**ret_policy_digest
) {
4236 assert(pubkey_pcr_mask
== 0 || public);
4238 log_debug("Building sealing policy.");
4240 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
4241 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
4245 log_debug("Selected TPM2 PCRs are not initialized on this system.");
4248 if (pubkey_pcr_mask
!= 0 && pcrlock_policy
)
4249 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Policies with both signed PCR and pcrlock are currently not supported.");
4251 if (pubkey_pcr_mask
!= 0) {
4252 TPML_PCR_SELECTION pcr_selection
;
4253 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
4254 r
= tpm2_policy_authorize(c
, session
, &pcr_selection
, public, fp
, fp_size
, signature_json
, NULL
);
4259 if (pcrlock_policy
) {
4260 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*nv_handle
= NULL
;
4262 r
= tpm2_policy_super_pcr(
4265 &pcrlock_policy
->prediction
,
4266 pcrlock_policy
->algorithm
);
4270 r
= tpm2_deserialize(
4272 pcrlock_policy
->nv_handle
.iov_base
,
4273 pcrlock_policy
->nv_handle
.iov_len
,
4278 r
= tpm2_policy_authorize_nv(
4287 if (hash_pcr_mask
!= 0) {
4288 TPML_PCR_SELECTION pcr_selection
;
4289 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
4290 r
= tpm2_policy_pcr(c
, session
, &pcr_selection
, NULL
);
4296 r
= tpm2_policy_auth_value(c
, session
, NULL
);
4301 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
4309 static const struct {
4310 TPM2_ECC_CURVE tpm2_ecc_curve_id
;
4311 int openssl_ecc_curve_id
;
4312 } tpm2_openssl_ecc_curve_table
[] = {
4313 { TPM2_ECC_NIST_P192
, NID_X9_62_prime192v1
, },
4314 { TPM2_ECC_NIST_P224
, NID_secp224r1
, },
4315 { TPM2_ECC_NIST_P256
, NID_X9_62_prime256v1
, },
4316 { TPM2_ECC_NIST_P384
, NID_secp384r1
, },
4317 { TPM2_ECC_NIST_P521
, NID_secp521r1
, },
4318 { TPM2_ECC_SM2_P256
, NID_sm2
, },
4321 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id
, TPM2_ECC_CURVE
*ret
) {
4324 FOREACH_ELEMENT(t
, tpm2_openssl_ecc_curve_table
)
4325 if (t
->openssl_ecc_curve_id
== openssl_ecc_curve_id
) {
4326 *ret
= t
->tpm2_ecc_curve_id
;
4330 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4331 "OpenSSL ECC curve id %d not supported.", openssl_ecc_curve_id
);
4334 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id
, int *ret
) {
4337 FOREACH_ELEMENT(t
, tpm2_openssl_ecc_curve_table
)
4338 if (t
->tpm2_ecc_curve_id
== tpm2_ecc_curve_id
) {
4339 *ret
= t
->openssl_ecc_curve_id
;
4343 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4344 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id
);
4347 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
4349 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
4355 const TPMT_PUBLIC
*p
= &public->publicArea
;
4357 case TPM2_ALG_ECC
: {
4359 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
4363 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
4364 return ecc_pkey_from_curve_x_y(
4372 case TPM2_ALG_RSA
: {
4373 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4374 * zero indicates that the exponent is the default of 2^16 + 1". */
4375 uint32_t exponent
= htobe32(p
->parameters
.rsaDetail
.exponent
?: TPM2_RSA_DEFAULT_EXPONENT
);
4376 return rsa_pkey_from_n_e(
4377 p
->unique
.rsa
.buffer
,
4384 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4385 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
4389 /* Be careful before changing anything in this function, as the TPM key "name" is calculated using the entire
4390 * TPMT_PUBLIC (after marshalling), and that "name" is used (for example) to calculate the policy hash for
4391 * the Authorize policy. So we must ensure this conversion of a PEM to TPM2B_PUBLIC does not change the
4392 * "name", because it would break unsealing of previously-sealed objects that used (for example)
4393 * tpm2_calculate_policy_authorize(). See bug #30546. */
4394 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY
*pkey
, TPM2B_PUBLIC
*ret
) {
4400 TPMT_PUBLIC
public = {
4401 .nameAlg
= TPM2_ALG_SHA256
,
4402 .objectAttributes
= TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
,
4403 .parameters
.asymDetail
= {
4404 .symmetric
.algorithm
= TPM2_ALG_NULL
,
4405 .scheme
.scheme
= TPM2_ALG_NULL
,
4409 #if OPENSSL_VERSION_MAJOR >= 3
4410 key_id
= EVP_PKEY_get_id(pkey
);
4412 key_id
= EVP_PKEY_id(pkey
);
4417 public.type
= TPM2_ALG_ECC
;
4420 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
4421 size_t x_size
, y_size
;
4422 r
= ecc_pkey_to_curve_x_y(pkey
, &curve_id
, &x
, &x_size
, &y
, &y_size
);
4424 return log_debug_errno(r
, "Could not get ECC key curve/x/y: %m");
4426 TPM2_ECC_CURVE curve
;
4427 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
4431 public.parameters
.eccDetail
.curveID
= curve
;
4433 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
4435 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
4437 return log_debug_errno(r
, "ECC key x size %zu too large.", x_size
);
4439 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
4441 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
4443 return log_debug_errno(r
, "ECC key y size %zu too large.", y_size
);
4445 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
4449 case EVP_PKEY_RSA
: {
4450 public.type
= TPM2_ALG_RSA
;
4452 _cleanup_free_
void *n
= NULL
, *e
= NULL
;
4453 size_t n_size
, e_size
;
4454 r
= rsa_pkey_to_n_e(pkey
, &n
, &n_size
, &e
, &e_size
);
4456 return log_debug_errno(r
, "Could not get RSA key n/e: %m");
4458 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
4460 return log_debug_errno(r
, "RSA key n size %zu too large.", n_size
);
4462 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
4463 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
4465 if (sizeof(uint32_t) < e_size
)
4466 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
4467 "RSA key e size %zu too large.", e_size
);
4469 uint32_t exponent
= 0;
4470 memcpy(&exponent
, e
, e_size
);
4471 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
4473 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4474 * zero indicates that the exponent is the default of 2^16 + 1". However, we have no reason
4475 * to special case it in our PEM->TPM2B_PUBLIC conversion, and doing so could break backwards
4476 * compatibility, so even if it is the "default" value of 0x10001, we do not set it to 0. */
4477 public.parameters
.rsaDetail
.exponent
= exponent
;
4482 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4483 "EVP_PKEY type %d not supported.", key_id
);
4486 *ret
= (TPM2B_PUBLIC
) {
4487 .size
= sizeof(public),
4488 .publicArea
= public,
4495 int tpm2_tpm2b_public_to_fingerprint(
4496 const TPM2B_PUBLIC
*public,
4497 void **ret_fingerprint
,
4498 size_t *ret_fingerprint_size
) {
4504 assert(ret_fingerprint
);
4505 assert(ret_fingerprint_size
);
4507 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4508 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
4512 /* Hardcode fingerprint to SHA256 */
4513 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
4515 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4519 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
4526 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4527 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
4531 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
4533 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4537 /* Marshal the public, private, and seed objects into a single nonstandard 'blob'. The public and private
4538 * objects are required, while the seed is optional. This is not a (publicly) standard format, this is
4539 * specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
4540 * tpm2_unmarshal_blob(). */
4541 int tpm2_marshal_blob(
4542 const TPM2B_PUBLIC
*public,
4543 const TPM2B_PRIVATE
*private,
4544 const TPM2B_ENCRYPTED_SECRET
*seed
,
4546 size_t *ret_blob_size
) {
4553 assert(ret_blob_size
);
4555 size_t max_size
= sizeof(*private) + sizeof(*public);
4557 max_size
+= sizeof(*seed
);
4559 _cleanup_free_
void *blob
= malloc(max_size
);
4561 return log_oom_debug();
4563 size_t blob_size
= 0;
4564 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
4565 if (rc
!= TSS2_RC_SUCCESS
)
4566 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4567 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
4569 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
4570 if (rc
!= TSS2_RC_SUCCESS
)
4571 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4572 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
4575 rc
= sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal(seed
, blob
, max_size
, &blob_size
);
4576 if (rc
!= TSS2_RC_SUCCESS
)
4577 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4578 "Failed to marshal encrypted seed: %s", sym_Tss2_RC_Decode(rc
));
4581 *ret_blob
= TAKE_PTR(blob
);
4582 *ret_blob_size
= blob_size
;
4587 /* Unmarshal the 'blob' into public, private, and seed objects. The public and private objects are required
4588 * in the 'blob', while the seed is optional. This is not a (publicly) standard format, this is specific to
4589 * how we currently store the sealed object. This expects the 'blob' to have been created by
4590 * tpm2_marshal_blob(). */
4591 int tpm2_unmarshal_blob(
4594 TPM2B_PUBLIC
*ret_public
,
4595 TPM2B_PRIVATE
*ret_private
,
4596 TPM2B_ENCRYPTED_SECRET
*ret_seed
) {
4602 assert(ret_private
);
4605 TPM2B_PRIVATE
private = {};
4607 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob
, blob_size
, &offset
, &private);
4608 if (rc
!= TSS2_RC_SUCCESS
)
4609 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4610 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
4612 TPM2B_PUBLIC
public = {};
4613 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob
, blob_size
, &offset
, &public);
4614 if (rc
!= TSS2_RC_SUCCESS
)
4615 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4616 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
4618 TPM2B_ENCRYPTED_SECRET seed
= {};
4619 if (blob_size
> offset
) {
4620 rc
= sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal(blob
, blob_size
, &offset
, &seed
);
4621 if (rc
!= TSS2_RC_SUCCESS
)
4622 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4623 "Failed to unmarshal encrypted seed: %s", sym_Tss2_RC_Decode(rc
));
4626 *ret_public
= public;
4627 *ret_private
= private;
4633 /* Calculate a serialized handle. Once the upstream tpm2-tss library provides an api to do this, we can
4634 * remove this function. The addition of this functionality in tpm2-tss may be tracked here:
4635 * https://github.com/tpm2-software/tpm2-tss/issues/2575 */
4636 int tpm2_calculate_serialize(
4638 const TPM2B_NAME
*name
,
4639 const TPM2B_PUBLIC
*public,
4640 void **ret_serialized
,
4641 size_t *ret_serialized_size
) {
4647 assert(ret_serialized
);
4648 assert(ret_serialized_size
);
4650 size_t max_size
= sizeof(TPM2_HANDLE
) + sizeof(TPM2B_NAME
) + sizeof(uint32_t) + sizeof(TPM2B_PUBLIC
);
4651 _cleanup_free_
void *serialized
= malloc(max_size
);
4653 return log_oom_debug();
4655 size_t serialized_size
= 0;
4656 rc
= sym_Tss2_MU_TPM2_HANDLE_Marshal(handle
, serialized
, max_size
, &serialized_size
);
4657 if (rc
!= TSS2_RC_SUCCESS
)
4658 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4659 "Failed to marshal tpm handle: %s", sym_Tss2_RC_Decode(rc
));
4661 rc
= sym_Tss2_MU_TPM2B_NAME_Marshal(name
, serialized
, max_size
, &serialized_size
);
4662 if (rc
!= TSS2_RC_SUCCESS
)
4663 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4664 "Failed to marshal name: %s", sym_Tss2_RC_Decode(rc
));
4666 /* This is defined (non-publicly) in the tpm2-tss source as IESYSC_KEY_RSRC, to a value of "1". */
4667 rc
= sym_Tss2_MU_UINT32_Marshal(UINT32_C(1), serialized
, max_size
, &serialized_size
);
4668 if (rc
!= TSS2_RC_SUCCESS
)
4669 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4670 "Failed to marshal esys resource id: %s", sym_Tss2_RC_Decode(rc
));
4672 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, serialized
, max_size
, &serialized_size
);
4673 if (rc
!= TSS2_RC_SUCCESS
)
4674 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4675 "Failed to marshal public: %s", sym_Tss2_RC_Decode(rc
));
4677 *ret_serialized
= TAKE_PTR(serialized
);
4678 *ret_serialized_size
= serialized_size
;
4683 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
4684 * across restarts of the TPM or reboots (assuming the handle is persistent). */
4687 const Tpm2Handle
*handle
,
4688 void **ret_serialized
,
4689 size_t *ret_serialized_size
) {
4695 assert(ret_serialized
);
4696 assert(ret_serialized_size
);
4698 _cleanup_(Esys_Freep
) unsigned char *serialized
= NULL
;
4700 rc
= sym_Esys_TR_Serialize(c
->esys_context
, handle
->esys_handle
, &serialized
, &size
);
4701 if (rc
!= TSS2_RC_SUCCESS
)
4702 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4703 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc
));
4705 *ret_serialized
= TAKE_PTR(serialized
);
4706 *ret_serialized_size
= size
;
4711 int tpm2_deserialize(
4713 const void *serialized
,
4714 size_t serialized_size
,
4715 Tpm2Handle
**ret_handle
) {
4724 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
4725 r
= tpm2_handle_new(c
, &handle
);
4729 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
4730 handle
->flush
= false;
4732 rc
= sym_Esys_TR_Deserialize(c
->esys_context
, serialized
, serialized_size
, &handle
->esys_handle
);
4733 if (rc
!= TSS2_RC_SUCCESS
)
4734 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4735 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc
));
4737 *ret_handle
= TAKE_PTR(handle
);
4744 /* KDFa() as defined by the TPM spec. */
4745 static int tpm2_kdfa(
4746 TPMI_ALG_HASH hash_alg
,
4750 const void *context
,
4754 size_t *ret_key_len
) {
4760 assert(context
|| context_len
== 0);
4762 assert(bits
<= SIZE_MAX
- 7);
4764 assert(ret_key_len
);
4766 log_debug("Calculating KDFa().");
4768 size_t len
= DIV_ROUND_UP(bits
, 8);
4770 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4774 _cleanup_free_
void *buf
= NULL
;
4775 r
= kdf_kb_hmac_derive(
4791 /* If the number of bits results in a partial byte, the TPM spec requires we zero the unrequested
4792 * bits in the MSB (i.e. at index 0). From the spec Part 1 ("Architecture") section on Key
4793 * Derivation Function, specifically KDFa():
4795 * "The implied return from this function is a sequence of octets with a length equal to (bits + 7) /
4796 * 8. If bits is not an even multiple of 8, then the returned value occupies the least significant
4797 * bits of the returned octet array, and the additional, high-order bits in the 0th octet are
4798 * CLEAR. The unused bits of the most significant octet (MSO) are masked off and not shifted." */
4799 size_t partial
= bits
% 8;
4801 ((uint8_t*) buf
)[0] &= 0xffu
>> (8 - partial
);
4803 *ret_key
= TAKE_PTR(buf
);
4809 /* KDFe() as defined by the TPM spec. */
4810 static int tpm2_kdfe(
4811 TPMI_ALG_HASH hash_alg
,
4812 const void *shared_secret
,
4813 size_t shared_secret_len
,
4815 const void *context_u
,
4816 size_t context_u_size
,
4817 const void *context_v
,
4818 size_t context_v_size
,
4821 size_t *ret_key_len
) {
4825 assert(shared_secret
);
4830 assert(bits
<= SIZE_MAX
- 7);
4832 assert(ret_key_len
);
4834 log_debug("Calculating KDFe().");
4836 size_t len
= DIV_ROUND_UP(bits
, 8);
4838 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4842 size_t info_len
= strlen(label
) + 1 + context_u_size
+ context_v_size
;
4843 _cleanup_free_
void *info
= malloc(info_len
);
4845 return log_oom_debug();
4847 void *end
= mempcpy(mempcpy(stpcpy(info
, label
) + 1, context_u
, context_u_size
), context_v
, context_v_size
);
4848 /* assert we copied exactly the right amount that we allocated */
4849 assert(end
> info
&& (uintptr_t) end
- (uintptr_t) info
== info_len
);
4851 _cleanup_free_
void *buf
= NULL
;
4865 *ret_key
= TAKE_PTR(buf
);
4871 static int tpm2_calculate_seal_public(
4872 const TPM2B_PUBLIC
*parent
,
4873 const TPMA_OBJECT
*attributes
,
4874 const TPM2B_DIGEST
*policy
,
4875 const TPM2B_DIGEST
*seed
,
4878 TPM2B_PUBLIC
*ret
) {
4887 log_debug("Calculating public part of sealed object.");
4889 struct iovec data
[] = {
4890 IOVEC_MAKE((void*) seed
->buffer
, seed
->size
),
4891 IOVEC_MAKE((void*) secret
, secret_size
),
4893 TPM2B_DIGEST unique
;
4894 r
= tpm2_digest_many(
4895 parent
->publicArea
.nameAlg
,
4899 /* extend= */ false);
4903 *ret
= (TPM2B_PUBLIC
) {
4904 .size
= sizeof(TPMT_PUBLIC
),
4906 .type
= TPM2_ALG_KEYEDHASH
,
4907 .nameAlg
= parent
->publicArea
.nameAlg
,
4908 .objectAttributes
= attributes
? *attributes
: 0,
4909 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, unique
.size
),
4910 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
4911 .unique
.keyedHash
= unique
,
4918 static int tpm2_calculate_seal_private(
4919 const TPM2B_PUBLIC
*parent
,
4920 const TPM2B_NAME
*name
,
4922 const TPM2B_DIGEST
*seed
,
4925 TPM2B_PRIVATE
*ret
) {
4936 log_debug("Calculating private part of sealed object.");
4938 _cleanup_free_
void *storage_key
= NULL
;
4939 size_t storage_key_size
;
4940 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4946 (size_t) parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
4950 return log_debug_errno(r
, "Could not calculate storage key KDFa: %m");
4952 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
4956 size_t bits
= (size_t) r
* 8;
4958 _cleanup_free_
void *integrity_key
= NULL
;
4959 size_t integrity_key_size
;
4960 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4964 /* context= */ NULL
,
4968 &integrity_key_size
);
4970 return log_debug_errno(r
, "Could not calculate integrity key KDFa: %m");
4972 TPM2B_AUTH auth
= {};
4974 r
= tpm2_auth_value_from_pin(parent
->publicArea
.nameAlg
, pin
, &auth
);
4979 TPM2B_SENSITIVE sensitive
= {
4980 .size
= sizeof(TPMT_SENSITIVE
),
4982 .sensitiveType
= TPM2_ALG_KEYEDHASH
,
4985 .sensitive
.bits
= TPM2B_SENSITIVE_DATA_MAKE(secret
, secret_size
),
4989 _cleanup_free_
void *marshalled_sensitive
= malloc(sizeof(sensitive
));
4990 if (!marshalled_sensitive
)
4991 return log_oom_debug();
4993 size_t marshalled_sensitive_size
= 0;
4994 rc
= sym_Tss2_MU_TPM2B_SENSITIVE_Marshal(
4996 marshalled_sensitive
,
4998 &marshalled_sensitive_size
);
4999 if (rc
!= TSS2_RC_SUCCESS
)
5000 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5001 "Failed to marshal sensitive: %s", sym_Tss2_RC_Decode(rc
));
5003 const char *sym_alg
= tpm2_sym_alg_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.algorithm
);
5007 const char *sym_mode
= tpm2_sym_mode_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.mode
.sym
);
5011 _cleanup_free_
void *encrypted_sensitive
= NULL
;
5012 size_t encrypted_sensitive_size
;
5015 parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
5017 storage_key
, storage_key_size
,
5018 /* iv= */ NULL
, /* n_iv= */ 0,
5019 marshalled_sensitive
, marshalled_sensitive_size
,
5020 &encrypted_sensitive
, &encrypted_sensitive_size
);
5024 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
5028 _cleanup_free_
void *hmac_buffer
= NULL
;
5029 size_t hmac_size
= 0;
5030 struct iovec hmac_data
[] = {
5031 IOVEC_MAKE((void*) encrypted_sensitive
, encrypted_sensitive_size
),
5032 IOVEC_MAKE((void*) name
->name
, name
->size
),
5034 r
= openssl_hmac_many(
5039 ELEMENTSOF(hmac_data
),
5045 TPM2B_DIGEST outer_hmac
= TPM2B_DIGEST_MAKE(hmac_buffer
, hmac_size
);
5047 TPM2B_PRIVATE
private = {};
5048 size_t private_size
= 0;
5049 rc
= sym_Tss2_MU_TPM2B_DIGEST_Marshal(
5052 sizeof(private.buffer
),
5054 if (rc
!= TSS2_RC_SUCCESS
)
5055 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5056 "Failed to marshal digest: %s", sym_Tss2_RC_Decode(rc
));
5057 private.size
= private_size
;
5059 assert(sizeof(private.buffer
) - private.size
>= encrypted_sensitive_size
);
5060 memcpy_safe(&private.buffer
[private.size
], encrypted_sensitive
, encrypted_sensitive_size
);
5061 private.size
+= encrypted_sensitive_size
;
5068 static int tpm2_calculate_seal_rsa_seed(
5069 const TPM2B_PUBLIC
*parent
,
5071 size_t *ret_seed_size
,
5072 void **ret_encrypted_seed
,
5073 size_t *ret_encrypted_seed_size
) {
5079 assert(ret_seed_size
);
5080 assert(ret_encrypted_seed
);
5081 assert(ret_encrypted_seed_size
);
5083 log_debug("Calculating encrypted seed for RSA sealed object.");
5085 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
5086 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
5088 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
5090 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
5094 size_t seed_size
= (size_t) r
;
5096 _cleanup_free_
void *seed
= malloc(seed_size
);
5098 return log_oom_debug();
5100 r
= crypto_random_bytes(seed
, seed_size
);
5102 return log_debug_errno(r
, "Failed to generate random seed: %m");
5104 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
5108 _cleanup_free_
void *encrypted_seed
= NULL
;
5109 size_t encrypted_seed_size
;
5110 r
= rsa_oaep_encrypt_bytes(
5117 &encrypted_seed_size
);
5119 return log_debug_errno(r
, "Could not RSA-OAEP encrypt random seed: %m");
5121 *ret_seed
= TAKE_PTR(seed
);
5122 *ret_seed_size
= seed_size
;
5123 *ret_encrypted_seed
= TAKE_PTR(encrypted_seed
);
5124 *ret_encrypted_seed_size
= encrypted_seed_size
;
5129 static int tpm2_calculate_seal_ecc_seed(
5130 const TPM2B_PUBLIC
*parent
,
5132 size_t *ret_seed_size
,
5133 void **ret_encrypted_seed
,
5134 size_t *ret_encrypted_seed_size
) {
5141 assert(ret_seed_size
);
5142 assert(ret_encrypted_seed
);
5143 assert(ret_encrypted_seed_size
);
5145 log_debug("Calculating encrypted seed for ECC sealed object.");
5147 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
5148 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
5150 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
5153 r
= ecc_pkey_to_curve_x_y(
5156 /* ret_x= */ NULL
, /* ret_x_size= */ 0,
5157 /* ret_y= */ NULL
, /* ret_y_size= */ 0);
5161 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
5162 r
= ecc_pkey_new(curve_id
, &pkey
);
5166 _cleanup_free_
void *shared_secret
= NULL
;
5167 size_t shared_secret_size
;
5168 r
= ecc_ecdh(pkey
, parent_pkey
, &shared_secret
, &shared_secret_size
);
5170 return log_debug_errno(r
, "Could not generate ECC shared secret: %m");
5172 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
5173 size_t x_size
, y_size
;
5174 r
= ecc_pkey_to_curve_x_y(pkey
, /* curve_id= */ NULL
, &x
, &x_size
, &y
, &y_size
);
5176 return log_debug_errno(r
, "Could not get ECC get x/y: %m");
5178 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
5180 return log_debug_errno(r
, "ECC point x size %zu is too large: %m", x_size
);
5182 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
5184 return log_debug_errno(r
, "ECC point y size %zu is too large: %m", y_size
);
5186 TPMS_ECC_POINT point
= {
5187 .x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
),
5188 .y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
),
5191 _cleanup_free_
void *encrypted_seed
= malloc(sizeof(point
));
5192 if (!encrypted_seed
)
5193 return log_oom_debug();
5195 size_t encrypted_seed_size
= 0;
5196 rc
= sym_Tss2_MU_TPMS_ECC_POINT_Marshal(&point
, encrypted_seed
, sizeof(point
), &encrypted_seed_size
);
5197 if (rc
!= TPM2_RC_SUCCESS
)
5198 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5199 "Failed to marshal ECC point: %s", sym_Tss2_RC_Decode(rc
));
5201 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
5205 size_t bits
= (size_t) r
* 8;
5207 _cleanup_free_
void *seed
= NULL
;
5208 size_t seed_size
= 0; /* Explicit initialization to appease gcc */
5209 r
= tpm2_kdfe(parent
->publicArea
.nameAlg
,
5215 parent
->publicArea
.unique
.ecc
.x
.buffer
,
5216 parent
->publicArea
.unique
.ecc
.x
.size
,
5221 return log_debug_errno(r
, "Could not calculate KDFe: %m");
5223 *ret_seed
= TAKE_PTR(seed
);
5224 *ret_seed_size
= seed_size
;
5225 *ret_encrypted_seed
= TAKE_PTR(encrypted_seed
);
5226 *ret_encrypted_seed_size
= encrypted_seed_size
;
5231 static int tpm2_calculate_seal_seed(
5232 const TPM2B_PUBLIC
*parent
,
5233 TPM2B_DIGEST
*ret_seed
,
5234 TPM2B_ENCRYPTED_SECRET
*ret_encrypted_seed
) {
5240 assert(ret_encrypted_seed
);
5242 log_debug("Calculating encrypted seed for sealed object.");
5244 _cleanup_free_
void *seed
= NULL
, *encrypted_seed
= NULL
;
5245 size_t seed_size
= 0, encrypted_seed_size
= 0; /* Explicit initialization to appease gcc */
5246 if (parent
->publicArea
.type
== TPM2_ALG_RSA
)
5247 r
= tpm2_calculate_seal_rsa_seed(parent
, &seed
, &seed_size
, &encrypted_seed
, &encrypted_seed_size
);
5248 else if (parent
->publicArea
.type
== TPM2_ALG_ECC
)
5249 r
= tpm2_calculate_seal_ecc_seed(parent
, &seed
, &seed_size
, &encrypted_seed
, &encrypted_seed_size
);
5251 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5252 "Unsupported parent key type 0x%" PRIx16
, parent
->publicArea
.type
);
5254 return log_debug_errno(r
, "Could not calculate encrypted seed: %m");
5256 *ret_seed
= TPM2B_DIGEST_MAKE(seed
, seed_size
);
5257 *ret_encrypted_seed
= TPM2B_ENCRYPTED_SECRET_MAKE(encrypted_seed
, encrypted_seed_size
);
5262 #endif /* HAVE_OPENSSL */
5264 int tpm2_calculate_seal(
5265 TPM2_HANDLE parent_handle
,
5266 const TPM2B_PUBLIC
*parent_public
,
5267 const TPMA_OBJECT
*attributes
,
5268 const struct iovec
*secret
,
5269 const TPM2B_DIGEST
*policy
,
5271 struct iovec
*ret_secret
,
5272 struct iovec
*ret_blob
,
5273 struct iovec
*ret_serialized_parent
) {
5278 assert(parent_public
);
5279 assert(iovec_is_valid(secret
));
5280 assert(secret
|| ret_secret
);
5281 assert(!(secret
&& ret_secret
)); /* Either provide a secret, or we create one, but not both */
5283 assert(ret_serialized_parent
);
5285 log_debug("Calculating sealed object.");
5287 /* Default to the SRK. */
5288 if (parent_handle
== 0)
5289 parent_handle
= TPM2_SRK_HANDLE
;
5291 switch (TPM2_HANDLE_TYPE(parent_handle
)) {
5292 case TPM2_HT_PERSISTENT
:
5293 case TPM2_HT_NV_INDEX
:
5295 case TPM2_HT_TRANSIENT
:
5296 log_warning("Handle is transient, sealed secret may not be recoverable.");
5299 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5300 "Handle 0x%" PRIx32
" not persistent, transient, or NV.",
5304 _cleanup_(iovec_done_erase
) struct iovec generated_secret
= {};
5306 /* No secret provided, generate a random secret. We use SHA256 digest length, though it can
5307 * be up to TPM2_MAX_SEALED_DATA. The secret length is not limited to the nameAlg hash
5309 generated_secret
.iov_len
= TPM2_SHA256_DIGEST_SIZE
;
5310 generated_secret
.iov_base
= malloc(generated_secret
.iov_len
);
5311 if (!generated_secret
.iov_base
)
5312 return log_oom_debug();
5314 r
= crypto_random_bytes(generated_secret
.iov_base
, generated_secret
.iov_len
);
5316 return log_debug_errno(r
, "Failed to generate secret key: %m");
5318 secret
= &generated_secret
;
5321 if (secret
->iov_len
> TPM2_MAX_SEALED_DATA
)
5322 return log_debug_errno(SYNTHETIC_ERRNO(EOVERFLOW
),
5323 "Secret size %zu too large, limit is %d bytes.",
5324 secret
->iov_len
, TPM2_MAX_SEALED_DATA
);
5326 TPM2B_DIGEST random_seed
;
5327 TPM2B_ENCRYPTED_SECRET seed
;
5328 r
= tpm2_calculate_seal_seed(parent_public
, &random_seed
, &seed
);
5332 TPM2B_PUBLIC
public;
5333 r
= tpm2_calculate_seal_public(parent_public
, attributes
, policy
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &public);
5338 r
= tpm2_calculate_pubkey_name(&public.publicArea
, &name
);
5342 TPM2B_PRIVATE
private;
5343 r
= tpm2_calculate_seal_private(parent_public
, &name
, pin
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &private);
5347 _cleanup_(iovec_done
) struct iovec blob
= {};
5348 r
= tpm2_marshal_blob(&public, &private, &seed
, &blob
.iov_base
, &blob
.iov_len
);
5350 return log_debug_errno(r
, "Could not create sealed blob: %m");
5352 TPM2B_NAME parent_name
;
5353 r
= tpm2_calculate_pubkey_name(&parent_public
->publicArea
, &parent_name
);
5357 _cleanup_(iovec_done
) struct iovec serialized_parent
= {};
5358 r
= tpm2_calculate_serialize(
5362 &serialized_parent
.iov_base
,
5363 &serialized_parent
.iov_len
);
5368 *ret_secret
= TAKE_STRUCT(generated_secret
);
5369 *ret_blob
= TAKE_STRUCT(blob
);
5370 *ret_serialized_parent
= TAKE_STRUCT(serialized_parent
);
5373 #else /* HAVE_OPENSSL */
5374 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
5378 int tpm2_seal(Tpm2Context
*c
,
5379 uint32_t seal_key_handle
,
5380 const TPM2B_DIGEST
*policy
,
5382 struct iovec
*ret_secret
,
5383 struct iovec
*ret_blob
,
5384 uint16_t *ret_primary_alg
,
5385 struct iovec
*ret_srk
) {
5387 uint16_t primary_alg
= 0;
5393 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
5394 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
5395 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
5396 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
5397 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
5398 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
5399 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
5400 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
5401 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
5402 * LUKS2 JSON header.
5404 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
5405 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
5406 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
5407 * binding the unlocking to the TPM2 chip. */
5409 usec_t start
= now(CLOCK_MONOTONIC
);
5411 TPMA_OBJECT hmac_attributes
=
5412 TPMA_OBJECT_FIXEDTPM
|
5413 TPMA_OBJECT_FIXEDPARENT
;
5415 /* If protected by PIN, a user-selected low-entropy password, enable DA protection.
5416 Without a PIN, the key's left protected only by a PCR policy, which does not benefit
5417 from DA protection. */
5418 hmac_attributes
|= pin
? 0 : TPMA_OBJECT_NODA
;
5420 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
5421 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
5422 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
5423 TPMT_PUBLIC hmac_template
= {
5424 .type
= TPM2_ALG_KEYEDHASH
,
5425 .nameAlg
= TPM2_ALG_SHA256
,
5426 .objectAttributes
= hmac_attributes
,
5427 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
5428 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
5429 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
5432 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
5433 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
5436 CLEANUP_ERASE(hmac_sensitive
);
5439 r
= tpm2_auth_value_from_pin(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
5444 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
5446 (void) tpm2_credit_random(c
);
5448 log_debug("Generating secret key data.");
5450 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
5452 return log_debug_errno(r
, "Failed to generate secret key: %m");
5454 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
5456 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
5458 if (IN_SET(seal_key_handle
, 0, TPM2_SRK_HANDLE
)) {
5459 r
= tpm2_get_or_create_srk(
5461 /* session= */ NULL
,
5463 /* ret_name= */ NULL
,
5464 /* ret_qname= */ NULL
,
5468 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle
), TPM2_HT_TRANSIENT
, TPM2_HT_PERSISTENT
)) {
5469 r
= tpm2_index_to_handle(
5472 /* session= */ NULL
,
5474 /* ret_name= */ NULL
,
5475 /* ret_qname= */ NULL
,
5480 /* We do NOT automatically create anything other than the SRK */
5481 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
5482 "No handle found at index 0x%" PRIx32
, seal_key_handle
);
5484 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5485 "Seal key handle 0x%" PRIx32
" is neither transient nor persistent.",
5488 primary_alg
= primary_public
->publicArea
.type
;
5490 if (seal_key_handle
!= 0)
5491 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
5493 /* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
5494 primary_alg
= TPM2_ALG_ECC
;
5496 TPM2B_PUBLIC
template = {
5497 .size
= sizeof(TPMT_PUBLIC
),
5499 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5501 return log_debug_errno(r
, "Could not get legacy ECC template: %m");
5503 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
5504 primary_alg
= TPM2_ALG_RSA
;
5506 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5508 return log_debug_errno(r
, "Could not get legacy RSA template: %m");
5510 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
))
5511 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5512 "TPM does not support either ECC or RSA legacy template.");
5515 r
= tpm2_create_primary(
5517 /* session= */ NULL
,
5519 /* sensitive= */ NULL
,
5520 /* ret_public= */ NULL
,
5526 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5527 r
= tpm2_make_encryption_session(c
, primary_handle
, /* bind_key= */ NULL
, &encryption_session
);
5531 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
5532 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
5533 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
5537 _cleanup_(iovec_done_erase
) struct iovec secret
= {};
5538 secret
.iov_base
= memdup(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
5539 if (!secret
.iov_base
)
5540 return log_oom_debug();
5541 secret
.iov_len
= hmac_sensitive
.data
.size
;
5543 log_debug("Marshalling private and public part of HMAC key.");
5545 _cleanup_(iovec_done
) struct iovec blob
= {};
5546 r
= tpm2_marshal_blob(public, private, /* seed= */ NULL
, &blob
.iov_base
, &blob
.iov_len
);
5548 return log_debug_errno(r
, "Could not create sealed blob: %m");
5551 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5554 _cleanup_(iovec_done
) struct iovec srk
= {};
5555 _cleanup_(Esys_Freep
) void *tmp
= NULL
;
5558 r
= tpm2_serialize(c
, primary_handle
, &tmp
, &tmp_size
);
5563 * make a copy since we don't want the caller to understand that
5564 * ESYS allocated the pointer. It would make tracking what deallocator
5565 * to use for srk in which context a PITA.
5567 srk
.iov_base
= memdup(tmp
, tmp_size
);
5569 return log_oom_debug();
5570 srk
.iov_len
= tmp_size
;
5572 *ret_srk
= TAKE_STRUCT(srk
);
5575 *ret_secret
= TAKE_STRUCT(secret
);
5576 *ret_blob
= TAKE_STRUCT(blob
);
5578 if (ret_primary_alg
)
5579 *ret_primary_alg
= primary_alg
;
5584 #define RETRY_UNSEAL_MAX 30u
5586 int tpm2_unseal(Tpm2Context
*c
,
5587 uint32_t hash_pcr_mask
,
5589 const struct iovec
*pubkey
,
5590 uint32_t pubkey_pcr_mask
,
5591 JsonVariant
*signature
,
5593 const Tpm2PCRLockPolicy
*pcrlock_policy
,
5594 uint16_t primary_alg
,
5595 const struct iovec
*blob
,
5596 const struct iovec
*known_policy_hash
,
5597 const struct iovec
*srk
,
5598 struct iovec
*ret_secret
) {
5603 assert(iovec_is_set(blob
));
5604 assert(iovec_is_valid(known_policy_hash
));
5605 assert(iovec_is_valid(pubkey
));
5608 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
5609 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
5611 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
5612 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
5613 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
5614 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
5615 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
5616 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5617 * and use it to unlock the LUKS2 volume. */
5619 usec_t start
= now(CLOCK_MONOTONIC
);
5621 TPM2B_PUBLIC
public;
5622 TPM2B_PRIVATE
private;
5623 TPM2B_ENCRYPTED_SECRET seed
= {};
5624 r
= tpm2_unmarshal_blob(blob
->iov_base
, blob
->iov_len
, &public, &private, &seed
);
5626 return log_debug_errno(r
, "Could not extract parts from blob: %m");
5628 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
5629 * so we need to handle that legacy situation. */
5630 if (pcr_bank
== UINT16_MAX
) {
5631 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
5636 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
5637 if (iovec_is_set(srk
)) {
5638 r
= tpm2_deserialize(c
, srk
->iov_base
, srk
->iov_len
, &primary_handle
);
5641 } else if (primary_alg
!= 0) {
5642 TPM2B_PUBLIC
template = {
5643 .size
= sizeof(TPMT_PUBLIC
),
5645 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5647 return log_debug_errno(r
, "Could not get legacy template: %m");
5649 r
= tpm2_create_primary(
5651 /* session= */ NULL
,
5653 /* sensitive= */ NULL
,
5654 /* ret_public= */ NULL
,
5659 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5660 "No SRK or primary alg provided.");
5662 if (seed
.size
> 0) {
5663 /* This is a calculated (or duplicated) sealed object, and must be imported. */
5664 _cleanup_free_ TPM2B_PRIVATE
*imported_private
= NULL
;
5667 /* session= */ NULL
,
5671 /* encryption_key= */ NULL
,
5672 /* symmetric= */ NULL
,
5677 private = *imported_private
;
5680 log_debug("Loading HMAC key into TPM.");
5683 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
5684 * gives you back a different key, the session initiation will fail. In the
5685 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
5686 * provides protections.
5688 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
5689 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
5693 TPM2B_PUBLIC pubkey_tpm2b
;
5694 _cleanup_(iovec_done
) struct iovec fp
= {};
5695 if (iovec_is_set(pubkey
)) {
5696 r
= tpm2_tpm2b_public_from_pem(pubkey
->iov_base
, pubkey
->iov_len
, &pubkey_tpm2b
);
5698 return log_debug_errno(r
, "Could not create TPMT_PUBLIC: %m");
5700 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
.iov_base
, &fp
.iov_len
);
5702 return log_debug_errno(r
, "Could not get key fingerprint: %m");
5706 * if a pin is set for the seal object, use it to bind the session
5707 * key to that object. This prevents active bus interposers from
5708 * faking a TPM and seeing the unsealed value. An active interposer
5709 * could fake a TPM, satisfying the encrypted session, and just
5710 * forward everything to the *real* TPM.
5712 r
= tpm2_set_auth(c
, hmac_key
, pin
);
5716 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
5717 for (unsigned i
= RETRY_UNSEAL_MAX
;; i
--) {
5718 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5719 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
5723 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*policy_session
= NULL
;
5724 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
5725 r
= tpm2_make_policy_session(
5733 r
= tpm2_build_sealing_policy(
5738 iovec_is_set(pubkey
) ? &pubkey_tpm2b
: NULL
,
5739 fp
.iov_base
, fp
.iov_len
,
5748 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
5749 * wait until the TPM2 tells us to go away. */
5750 if (iovec_is_set(known_policy_hash
) && memcmp_nn(policy_digest
->buffer
,
5751 policy_digest
->size
,
5752 known_policy_hash
->iov_base
,
5753 known_policy_hash
->iov_len
) != 0) {
5755 if (iovec_is_set(pubkey
) &&
5756 pubkey_tpm2b
.publicArea
.type
== TPM2_ALG_RSA
&&
5757 pubkey_tpm2b
.publicArea
.parameters
.rsaDetail
.exponent
== TPM2_RSA_DEFAULT_EXPONENT
) {
5758 /* Due to bug #30546, if using RSA pubkey with the default exponent, we may
5759 * need to set the exponent to the TPM special-case value of 0 and retry. */
5760 log_debug("Policy hash mismatch, retrying with RSA pubkey exponent set to 0.");
5761 pubkey_tpm2b
.publicArea
.parameters
.rsaDetail
.exponent
= 0;
5765 return log_debug_errno(SYNTHETIC_ERRNO(EPERM
),
5766 "Current policy digest does not match stored policy digest, cancelling "
5767 "TPM2 authentication attempt.");
5770 log_debug("Unsealing HMAC key.");
5772 rc
= sym_Esys_Unseal(
5774 hmac_key
->esys_handle
,
5775 policy_session
->esys_handle
,
5776 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
5779 if (rc
== TSS2_RC_SUCCESS
)
5781 if (rc
!= TPM2_RC_PCR_CHANGED
|| i
== 0)
5782 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5783 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc
));
5784 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i
);
5787 _cleanup_(iovec_done_erase
) struct iovec secret
= {};
5788 secret
.iov_base
= memdup(unsealed
->buffer
, unsealed
->size
);
5789 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
5790 if (!secret
.iov_base
)
5791 return log_oom_debug();
5792 secret
.iov_len
= unsealed
->size
;
5795 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5797 *ret_secret
= TAKE_STRUCT(secret
);
5802 static TPM2_HANDLE
generate_random_nv_index(void) {
5803 return TPM2_NV_INDEX_FIRST
+ (TPM2_HANDLE
) random_u64_range(TPM2_NV_INDEX_LAST
- TPM2_NV_INDEX_FIRST
+ 1);
5806 int tpm2_define_policy_nv_index(
5808 const Tpm2Handle
*session
,
5809 TPM2_HANDLE requested_nv_index
,
5810 const TPM2B_DIGEST
*write_policy
,
5811 TPM2_HANDLE
*ret_nv_index
,
5812 Tpm2Handle
**ret_nv_handle
,
5813 TPM2B_NV_PUBLIC
*ret_nv_public
) {
5815 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*new_handle
= NULL
;
5821 /* Allocates an nvindex to store a policy for use in PolicyAuthorizeNV in. This is where pcrlock then
5822 * stores its predicted PCR policies in. If 'requested_nv_index' will try to allocate the specified
5823 * nvindex, otherwise will find a free one, and use that. */
5825 r
= tpm2_handle_new(c
, &new_handle
);
5829 new_handle
->flush
= false; /* This is a persistent NV index, don't flush hence */
5831 for (unsigned try = 0; try < 25U; try++) {
5832 TPM2_HANDLE nv_index
;
5834 if (requested_nv_index
!= 0)
5835 nv_index
= requested_nv_index
;
5837 nv_index
= generate_random_nv_index();
5839 TPM2B_NV_PUBLIC public_info
= {
5840 .size
= sizeof_field(TPM2B_NV_PUBLIC
, nvPublic
),
5842 .nvIndex
= nv_index
,
5843 .nameAlg
= TPM2_ALG_SHA256
,
5844 .attributes
= TPM2_NT_ORDINARY
| TPMA_NV_WRITEALL
| TPMA_NV_POLICYWRITE
| TPMA_NV_OWNERREAD
,
5845 .dataSize
= offsetof(TPMT_HA
, digest
) + tpm2_hash_alg_to_size(TPM2_ALG_SHA256
),
5850 public_info
.nvPublic
.authPolicy
= *write_policy
;
5852 rc
= sym_Esys_NV_DefineSpace(
5854 /* authHandle= */ ESYS_TR_RH_OWNER
,
5855 /* shandle1= */ session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
5856 /* shandle2= */ ESYS_TR_NONE
,
5857 /* shandle3= */ ESYS_TR_NONE
,
5860 &new_handle
->esys_handle
);
5862 if (rc
== TSS2_RC_SUCCESS
) {
5863 log_debug("NV Index 0x%" PRIx32
" successfully allocated.", nv_index
);
5866 *ret_nv_index
= nv_index
;
5869 *ret_nv_handle
= TAKE_PTR(new_handle
);
5872 *ret_nv_public
= public_info
;
5876 if (rc
!= TPM2_RC_NV_DEFINED
)
5877 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5878 "Failed to allocate NV index: %s", sym_Tss2_RC_Decode(rc
));
5880 if (requested_nv_index
!= 0) {
5881 assert(nv_index
== requested_nv_index
);
5882 return log_debug_errno(SYNTHETIC_ERRNO(EEXIST
),
5883 "Requested NV index 0x%" PRIx32
" already taken.", requested_nv_index
);
5886 log_debug("NV index 0x%" PRIu32
" already taken, trying another one (%u tries left)", nv_index
, try);
5889 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5890 "Too many attempts trying to allocate NV index: %s", sym_Tss2_RC_Decode(rc
));
5893 int tpm2_write_policy_nv_index(
5895 const Tpm2Handle
*policy_session
,
5896 TPM2_HANDLE nv_index
,
5897 const Tpm2Handle
*nv_handle
,
5898 const TPM2B_DIGEST
*policy_digest
) {
5903 assert(policy_session
);
5905 assert(policy_digest
);
5907 if (policy_digest
->size
!= tpm2_hash_alg_to_size(TPM2_ALG_SHA256
))
5908 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Policy to store in NV index has wrong size.");
5911 .hashAlg
= TPM2_ALG_SHA256
,
5913 assert(policy_digest
->size
<= sizeof_field(TPMT_HA
, digest
));
5914 memcpy_safe(&ha
.digest
, policy_digest
->buffer
, policy_digest
->size
);
5916 TPM2B_MAX_NV_BUFFER buffer
= {};
5918 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, buffer
.buffer
, sizeof(buffer
.buffer
), &written
);
5919 if (rc
!= TSS2_RC_SUCCESS
)
5920 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5921 "Failed to marshal policy digest.");
5923 buffer
.size
= written
;
5925 rc
= sym_Esys_NV_Write(
5927 /* authHandle= */ nv_handle
->esys_handle
,
5928 /* nvIndex= */ nv_handle
->esys_handle
,
5929 /* shandle1= */ policy_session
->esys_handle
,
5930 /* shandle2= */ ESYS_TR_NONE
,
5931 /* shandle3= */ ESYS_TR_NONE
,
5934 if (rc
!= TSS2_RC_SUCCESS
)
5935 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5936 "Failed to write NV index: %s", sym_Tss2_RC_Decode(rc
));
5938 if (DEBUG_LOGGING
) {
5939 _cleanup_free_
char *h
= NULL
;
5940 h
= hexmem(policy_digest
->buffer
, policy_digest
->size
);
5941 log_debug("Written policy digest %s to NV index 0x%x", strnull(h
), nv_index
);
5947 int tpm2_undefine_policy_nv_index(
5949 const Tpm2Handle
*session
,
5950 TPM2_HANDLE nv_index
,
5951 const Tpm2Handle
*nv_handle
) {
5958 rc
= sym_Esys_NV_UndefineSpace(
5960 /* authHandle= */ ESYS_TR_RH_OWNER
,
5961 /* nvIndex= */ nv_handle
->esys_handle
,
5962 /* shandle1= */ session
? session
->esys_handle
: ESYS_TR_NONE
,
5963 /* shandle2= */ ESYS_TR_NONE
,
5964 /* shandle3= */ ESYS_TR_NONE
);
5965 if (rc
!= TSS2_RC_SUCCESS
)
5966 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5967 "Failed to undefine NV index: %s", sym_Tss2_RC_Decode(rc
));
5969 log_debug("Undefined NV index 0x%x", nv_index
);
5975 const struct iovec
*data
,
5976 const Tpm2Handle
*primary_handle
,
5977 const Tpm2Handle
*encryption_session
,
5978 const TPM2B_DIGEST
*policy
,
5979 struct iovec
*ret_public
,
5980 struct iovec
*ret_private
) {
5986 assert(primary_handle
);
5988 /* This is a generic version of tpm2_seal(), that doesn't imply any policy or any specific
5989 * combination of the two keypairs in their marshalling. tpm2_seal() is somewhat specific to the FDE
5990 * usecase. We probably should migrate tpm2_seal() to use tpm2_seal_data() eventually. */
5992 if (data
->iov_len
>= sizeof_field(TPMS_SENSITIVE_CREATE
, data
.buffer
))
5995 TPMT_PUBLIC hmac_template
= {
5996 .type
= TPM2_ALG_KEYEDHASH
,
5997 .nameAlg
= TPM2_ALG_SHA256
,
5998 .objectAttributes
= TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT
,
5999 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
6000 .unique
.keyedHash
.size
= data
->iov_len
,
6001 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
6004 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
6005 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
6008 CLEANUP_ERASE(hmac_sensitive
);
6010 memcpy_safe(hmac_sensitive
.data
.buffer
, data
->iov_base
, data
->iov_len
);
6012 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
6013 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
6014 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
6018 _cleanup_(iovec_done
) struct iovec public_blob
= {}, private_blob
= {};
6020 r
= tpm2_marshal_private(private, &private_blob
.iov_base
, &private_blob
.iov_len
);
6024 r
= tpm2_marshal_public(public, &public_blob
.iov_base
, &public_blob
.iov_len
);
6029 *ret_public
= TAKE_STRUCT(public_blob
);
6031 *ret_private
= TAKE_STRUCT(private_blob
);
6036 int tpm2_unseal_data(
6038 const struct iovec
*public_blob
,
6039 const struct iovec
*private_blob
,
6040 const Tpm2Handle
*primary_handle
,
6041 const Tpm2Handle
*policy_session
,
6042 const Tpm2Handle
*encryption_session
,
6043 struct iovec
*ret_data
) {
6049 assert(public_blob
);
6050 assert(private_blob
);
6051 assert(primary_handle
);
6053 TPM2B_PUBLIC
public;
6054 r
= tpm2_unmarshal_public(public_blob
->iov_base
, public_blob
->iov_len
, &public);
6058 TPM2B_PRIVATE
private;
6059 r
= tpm2_unmarshal_private(private_blob
->iov_base
, private_blob
->iov_len
, &private);
6063 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*what
= NULL
;
6064 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &what
);
6068 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
6069 rc
= sym_Esys_Unseal(
6072 policy_session
? policy_session
->esys_handle
: ESYS_TR_NONE
,
6073 encryption_session
? encryption_session
->esys_handle
: ESYS_TR_NONE
,
6076 if (rc
== TPM2_RC_PCR_CHANGED
)
6077 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE
),
6078 "PCR changed while unsealing.");
6079 if (rc
!= TSS2_RC_SUCCESS
)
6080 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
6081 "Failed to unseal data: %s", sym_Tss2_RC_Decode(rc
));
6083 _cleanup_(iovec_done
) struct iovec d
= {};
6084 d
= IOVEC_MAKE(memdup(unsealed
->buffer
, unsealed
->size
), unsealed
->size
);
6086 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
6089 return log_oom_debug();
6091 *ret_data
= TAKE_STRUCT(d
);
6094 #endif /* HAVE_TPM2 */
6096 int tpm2_list_devices(void) {
6098 _cleanup_(table_unrefp
) Table
*t
= NULL
;
6099 _cleanup_closedir_
DIR *d
= NULL
;
6104 return log_error_errno(r
, "TPM2 support is not installed.");
6106 t
= table_new("path", "device", "driver");
6110 d
= opendir("/sys/class/tpmrm");
6112 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
6113 if (errno
!= ENOENT
)
6117 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
6120 de
= readdir_no_dot(d
);
6124 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
6128 r
= readlink_malloc(device_path
, &device
);
6130 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
6132 driver_path
= path_join(device_path
, "driver");
6136 r
= readlink_malloc(driver_path
, &driver
);
6138 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
6141 node
= path_join("/dev", de
->d_name
);
6148 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
6149 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
6151 return table_log_add_error(r
);
6155 if (table_isempty(t
)) {
6156 log_info("No suitable TPM2 devices found.");
6160 r
= table_print(t
, stdout
);
6162 return log_error_errno(r
, "Failed to show device table: %m");
6166 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
6167 "TPM2 not supported on this build.");
6171 int tpm2_find_device_auto(char **ret
) {
6173 _cleanup_closedir_
DIR *d
= NULL
;
6178 return log_debug_errno(r
, "TPM2 support is not installed.");
6180 d
= opendir("/sys/class/tpmrm");
6182 log_debug_errno(errno
, "Failed to open /sys/class/tpmrm: %m");
6183 if (errno
!= ENOENT
)
6186 _cleanup_free_
char *node
= NULL
;
6191 de
= readdir_no_dot(d
);
6196 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
6197 "More than one TPM2 (tpmrm) device found.");
6199 node
= path_join("/dev", de
->d_name
);
6201 return log_oom_debug();
6205 *ret
= TAKE_PTR(node
);
6210 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
6212 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
6213 "TPM2 not supported on this build.");
6218 static const char* tpm2_userspace_event_type_table
[_TPM2_USERSPACE_EVENT_TYPE_MAX
] = {
6219 [TPM2_EVENT_PHASE
] = "phase",
6220 [TPM2_EVENT_FILESYSTEM
] = "filesystem",
6221 [TPM2_EVENT_VOLUME_KEY
] = "volume-key",
6222 [TPM2_EVENT_MACHINE_ID
] = "machine-id",
6225 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type
, Tpm2UserspaceEventType
);
6227 const char *tpm2_userspace_log_path(void) {
6228 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
6231 const char *tpm2_firmware_log_path(void) {
6232 return secure_getenv("SYSTEMD_MEASURE_LOG_FIRMWARE") ?: "/sys/kernel/security/tpm0/binary_bios_measurements";
6236 static int tpm2_userspace_log_open(void) {
6237 _cleanup_close_
int fd
= -EBADF
;
6242 e
= tpm2_userspace_log_path();
6243 (void) mkdir_parents(e
, 0755);
6245 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
6246 * because we use BSD file locking on it, and if anyone but root can access the file they can also
6247 * lock it, which we want to avoid. */
6248 fd
= open(e
, O_CREAT
|O_WRONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
, 0600);
6250 return log_debug_errno(errno
, "Failed to open TPM log file '%s' for writing, ignoring: %m", e
);
6252 if (flock(fd
, LOCK_EX
) < 0)
6253 return log_debug_errno(errno
, "Failed to lock TPM log file '%s', ignoring: %m", e
);
6255 if (fstat(fd
, &st
) < 0)
6256 return log_debug_errno(errno
, "Failed to fstat TPM log file '%s', ignoring: %m", e
);
6258 r
= stat_verify_regular(&st
);
6260 return log_debug_errno(r
, "TPM log file '%s' is not regular, ignoring: %m", e
);
6262 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
6263 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
6264 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
6265 * our assumed backend fs) doesn't know user xattrs. */
6266 if (st
.st_mode
& S_ISVTX
)
6267 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE
), "TPM log file '%s' aborted, ignoring.", e
);
6269 if (fchmod(fd
, 0600 | S_ISVTX
) < 0)
6270 return log_debug_errno(errno
, "Failed to chmod() TPM log file '%s', ignoring: %m", e
);
6275 static int tpm2_userspace_log(
6278 const TPML_DIGEST_VALUES
*values
,
6279 Tpm2UserspaceEventType event_type
,
6280 const char *description
) {
6282 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *array
= NULL
;
6283 _cleanup_free_
char *f
= NULL
;
6288 assert(values
->count
> 0);
6290 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
6291 * Format – the JSON flavour –
6292 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
6293 * ways from it, specifically:
6295 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
6296 * through the whole logs (include firmware logs) before knowing what the next value is we should
6297 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
6298 * it in when it uses the data.
6300 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
6301 * JSON array would mean that for each appending we'd have to read the whole log file fully into
6302 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
6303 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
6305 * It should be possible to convert this format in a relatively straight-forward way into the
6306 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
6307 * determined from the full dataset.
6309 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
6310 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
6311 * timestamp which can be used to order this measurement against possibly other measurements
6312 * independently done by other subsystems on the system.
6315 if (fd
< 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
6318 for (size_t i
= 0; i
< values
->count
; i
++) {
6319 const EVP_MD
*implementation
;
6322 assert_se(a
= tpm2_hash_alg_to_string(values
->digests
[i
].hashAlg
));
6323 assert_se(implementation
= EVP_get_digestbyname(a
));
6325 r
= json_variant_append_arrayb(
6326 &array
, JSON_BUILD_OBJECT(
6327 JSON_BUILD_PAIR_STRING("hashAlg", a
),
6328 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values
->digests
[i
].digest
, EVP_MD_size(implementation
)))));
6330 return log_debug_errno(r
, "Failed to append digest object to JSON array: %m");
6335 r
= sd_id128_get_boot(&boot_id
);
6337 return log_debug_errno(r
, "Failed to acquire boot ID: %m");
6339 r
= json_build(&v
, JSON_BUILD_OBJECT(
6340 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index
)),
6341 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array
)),
6342 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
6343 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
6344 JSON_BUILD_PAIR_CONDITION(description
, "string", JSON_BUILD_STRING(description
)),
6345 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id
)),
6346 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME
))),
6347 JSON_BUILD_PAIR_CONDITION(event_type
>= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type
)))))));
6349 return log_debug_errno(r
, "Failed to build log record JSON: %m");
6351 r
= json_variant_format(v
, JSON_FORMAT_SEQ
, &f
);
6353 return log_debug_errno(r
, "Failed to format JSON: %m");
6355 if (lseek(fd
, 0, SEEK_END
) < 0)
6356 return log_debug_errno(errno
, "Failed to seek to end of JSON log: %m");
6358 r
= loop_write(fd
, f
, SIZE_MAX
);
6360 return log_debug_errno(r
, "Failed to write JSON data to log: %m");
6363 return log_debug_errno(errno
, "Failed to sync JSON data: %m");
6365 /* Unset S_ISVTX again */
6366 if (fchmod(fd
, 0600) < 0)
6367 return log_debug_errno(errno
, "Failed to chmod() TPM log file, ignoring: %m");
6371 return log_debug_errno(r
, "Failed to sync JSON log: %m");
6377 int tpm2_extend_bytes(
6385 Tpm2UserspaceEventType event_type
,
6386 const char *description
) {
6389 _cleanup_close_
int log_fd
= -EBADF
;
6390 TPML_DIGEST_VALUES values
= {};
6394 assert(data
|| data_size
== 0);
6395 assert(secret
|| secret_size
== 0);
6397 if (data_size
== SIZE_MAX
)
6398 data_size
= strlen(data
);
6399 if (secret_size
== SIZE_MAX
)
6400 secret_size
= strlen(secret
);
6402 if (pcr_index
>= TPM2_PCRS_MAX
)
6403 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Can't measure into unsupported PCR %u, refusing.", pcr_index
);
6405 if (strv_isempty(banks
))
6408 STRV_FOREACH(bank
, banks
) {
6409 const EVP_MD
*implementation
;
6412 assert_se(implementation
= EVP_get_digestbyname(*bank
));
6414 if (values
.count
>= ELEMENTSOF(values
.digests
))
6415 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
6417 if ((size_t) EVP_MD_size(implementation
) > sizeof(values
.digests
[values
.count
].digest
))
6418 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Hash result too large for TPM2.");
6420 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
6422 return log_debug_errno(id
, "Can't map hash name to TPM2.");
6424 values
.digests
[values
.count
].hashAlg
= id
;
6426 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
6427 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
6428 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
6429 * secret for other purposes, maybe because it needs a shorter secret derived from it for
6430 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
6431 * private non-secret string instead. */
6432 if (secret_size
> 0) {
6433 if (!HMAC(implementation
, secret
, secret_size
, data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
))
6434 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to calculate HMAC of data to measure.");
6435 } else if (EVP_Digest(data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
, implementation
, NULL
) != 1)
6436 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to hash data to measure.");
6441 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
6442 * and our measurement and change either */
6443 log_fd
= tpm2_userspace_log_open();
6445 rc
= sym_Esys_PCR_Extend(
6447 ESYS_TR_PCR0
+ pcr_index
,
6452 if (rc
!= TSS2_RC_SUCCESS
)
6453 return log_debug_errno(
6454 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
6455 "Failed to measure into PCR %u: %s",
6457 sym_Tss2_RC_Decode(rc
));
6459 /* Now, write what we just extended to the log, too. */
6460 (void) tpm2_userspace_log(log_fd
, pcr_index
, &values
, event_type
, description
);
6463 #else /* HAVE_OPENSSL */
6464 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
6468 const uint16_t tpm2_hash_algorithms
[] = {
6476 assert_cc(ELEMENTSOF(tpm2_hash_algorithms
) == TPM2_N_HASH_ALGORITHMS
+ 1);
6478 static size_t tpm2_hash_algorithm_index(uint16_t algorithm
) {
6479 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++)
6480 if (tpm2_hash_algorithms
[i
] == algorithm
)
6486 TPM2B_DIGEST
*tpm2_pcr_prediction_result_get_hash(Tpm2PCRPredictionResult
*result
, uint16_t alg
) {
6491 alg_idx
= tpm2_hash_algorithm_index(alg
);
6492 if (alg_idx
== SIZE_MAX
) /* Algorithm not known? */
6495 if (result
->hash
[alg_idx
].size
<= 0) /* No hash value for this algorithm? */
6498 return result
->hash
+ alg_idx
;
6501 void tpm2_pcr_prediction_done(Tpm2PCRPrediction
*p
) {
6504 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++)
6505 ordered_set_free(p
->results
[pcr
]);
6508 static void tpm2_pcr_prediction_result_hash_func(const Tpm2PCRPredictionResult
*banks
, struct siphash
*state
) {
6511 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++)
6512 siphash24_compress_safe(banks
->hash
[i
].buffer
, banks
->hash
[i
].size
, state
);
6515 static int tpm2_pcr_prediction_result_compare_func(const Tpm2PCRPredictionResult
*a
, const Tpm2PCRPredictionResult
*b
) {
6521 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++) {
6522 r
= memcmp_nn(a
->hash
[i
].buffer
, a
->hash
[i
].size
,
6523 b
->hash
[i
].buffer
, b
->hash
[i
].size
);
6531 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
6532 tpm2_pcr_prediction_result_hash_ops
,
6533 Tpm2PCRPredictionResult
,
6534 tpm2_pcr_prediction_result_hash_func
,
6535 tpm2_pcr_prediction_result_compare_func
,
6536 Tpm2PCRPredictionResult
,
6539 static Tpm2PCRPredictionResult
*find_prediction_result_by_algorithm(OrderedSet
*set
, Tpm2PCRPredictionResult
*result
, size_t alg_idx
) {
6540 Tpm2PCRPredictionResult
*f
;
6543 assert(alg_idx
!= SIZE_MAX
);
6545 f
= ordered_set_get(set
, result
); /* Full match? */
6549 /* If this doesn't match full, then see if there an entry that at least matches by the relevant
6550 * algorithm (we are fine if predictions are "incomplete" in some algorithms) */
6552 ORDERED_SET_FOREACH(f
, set
)
6553 if (memcmp_nn(result
->hash
[alg_idx
].buffer
, result
->hash
[alg_idx
].size
,
6554 f
->hash
[alg_idx
].buffer
, f
->hash
[alg_idx
].size
) == 0)
6560 bool tpm2_pcr_prediction_equal(
6561 Tpm2PCRPrediction
*a
,
6562 Tpm2PCRPrediction
*b
,
6563 uint16_t algorithm
) {
6570 if (a
->pcrs
!= b
->pcrs
)
6573 size_t alg_idx
= tpm2_hash_algorithm_index(algorithm
);
6574 if (alg_idx
== SIZE_MAX
)
6577 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6578 Tpm2PCRPredictionResult
*banks
;
6580 ORDERED_SET_FOREACH(banks
, a
->results
[pcr
])
6581 if (!find_prediction_result_by_algorithm(b
->results
[pcr
], banks
, alg_idx
))
6584 ORDERED_SET_FOREACH(banks
, b
->results
[pcr
])
6585 if (!find_prediction_result_by_algorithm(a
->results
[pcr
], banks
, alg_idx
))
6592 int tpm2_pcr_prediction_to_json(
6593 const Tpm2PCRPrediction
*prediction
,
6595 JsonVariant
**ret
) {
6597 _cleanup_(json_variant_unrefp
) JsonVariant
*aj
= NULL
;
6603 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6604 _cleanup_(json_variant_unrefp
) JsonVariant
*vj
= NULL
;
6605 Tpm2PCRPredictionResult
*banks
;
6607 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6610 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6612 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6616 r
= json_variant_append_arrayb(
6618 JSON_BUILD_HEX(hash
->buffer
, hash
->size
));
6620 return log_error_errno(r
, "Failed to append hash variant to JSON array: %m");
6626 r
= json_variant_append_arrayb(
6629 JSON_BUILD_PAIR_INTEGER("pcr", pcr
),
6630 JSON_BUILD_PAIR_VARIANT("values", vj
)));
6632 return log_error_errno(r
, "Failed to append PCR variants to JSON array: %m");
6636 r
= json_variant_new_array(&aj
, NULL
, 0);
6641 *ret
= TAKE_PTR(aj
);
6645 int tpm2_pcr_prediction_from_json(
6646 Tpm2PCRPrediction
*prediction
,
6654 size_t alg_index
= tpm2_hash_algorithm_index(algorithm
);
6655 assert(alg_index
< TPM2_N_HASH_ALGORITHMS
);
6657 if (!json_variant_is_array(aj
))
6658 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR variant array is not an array.");
6661 JSON_VARIANT_ARRAY_FOREACH(pcr
, aj
) {
6662 JsonVariant
*nr
, *values
;
6664 nr
= json_variant_by_key(pcr
, "pcr");
6666 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks PCR index field");
6668 if (!json_variant_is_unsigned(nr
) ||
6669 json_variant_unsigned(nr
) >= TPM2_PCRS_MAX
)
6670 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry PCR index is not an integer in the range 0…23");
6672 values
= json_variant_by_key(pcr
, "values");
6674 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks values field");
6676 if (!json_variant_is_array(values
))
6677 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry values field is not an array");
6679 prediction
->pcrs
|= UINT32_C(1) << json_variant_unsigned(nr
);
6682 JSON_VARIANT_ARRAY_FOREACH(v
, values
) {
6683 _cleanup_free_
void *buffer
= NULL
;
6686 r
= json_variant_unhex(v
, &buffer
, &size
);
6688 return log_error_errno(r
, "Failed to decode PCR policy array hash value");
6691 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is zero.");
6693 if (size
> sizeof_field(TPM2B_DIGEST
, buffer
))
6694 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is too large.");
6696 _cleanup_free_ Tpm2PCRPredictionResult
*banks
= new0(Tpm2PCRPredictionResult
, 1);
6700 memcpy(banks
->hash
[alg_index
].buffer
, buffer
, size
);
6701 banks
->hash
[alg_index
].size
= size
;
6703 r
= ordered_set_ensure_put(prediction
->results
+ json_variant_unsigned(nr
), &tpm2_pcr_prediction_result_hash_ops
, banks
);
6704 if (r
== -EEXIST
) /* Let's allow duplicates */
6707 return log_error_errno(r
, "Failed to insert result into set: %m");
6716 int tpm2_calculate_policy_super_pcr(
6717 Tpm2PCRPrediction
*prediction
,
6719 TPM2B_DIGEST
*pcr_policy
) {
6723 assert_se(prediction
);
6724 assert_se(pcr_policy
);
6726 /* Start with a zero policy if not specified otherwise. */
6727 TPM2B_DIGEST super_pcr_policy_digest
= *pcr_policy
;
6729 /* First we look for all PCRs that have exactly one allowed hash value, and generate a single PolicyPCR policy from them */
6730 _cleanup_free_ Tpm2PCRValue
*single_values
= NULL
;
6731 size_t n_single_values
= 0;
6732 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6733 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6736 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6739 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6741 Tpm2PCRPredictionResult
*banks
= ASSERT_PTR(ordered_set_first(prediction
->results
[pcr
]));
6743 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6747 if (!GREEDY_REALLOC(single_values
, n_single_values
+ 1))
6750 single_values
[n_single_values
++] = TPM2_PCR_VALUE_MAKE(pcr
, algorithm
, *hash
);
6753 if (n_single_values
> 0) {
6754 /* Evolve policy based on the expected PCR value for what we found. */
6755 r
= tpm2_calculate_policy_pcr(
6758 &super_pcr_policy_digest
);
6763 /* Now deal with the PCRs for which we have variants, i.e. more than one allowed values */
6764 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6765 _cleanup_free_ TPM2B_DIGEST
*pcr_policy_digest_variants
= NULL
;
6766 size_t n_pcr_policy_digest_variants
= 0;
6767 Tpm2PCRPredictionResult
*banks
;
6769 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6772 if (ordered_set_size(prediction
->results
[pcr
]) <= 1) /* We only care for PCRs with 2 or more variants in this loop */
6775 if (ordered_set_size(prediction
->results
[pcr
]) > 8)
6776 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "PCR policies with more than 8 alternatives per PCR are currently not supported.");
6778 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6779 /* Start from the super PCR policy from the previous PCR we looked at so far. */
6780 TPM2B_DIGEST pcr_policy_digest
= super_pcr_policy_digest
;
6782 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6786 /* Evolve it based on the expected PCR value for this PCR */
6787 r
= tpm2_calculate_policy_pcr(
6788 &TPM2_PCR_VALUE_MAKE(
6792 /* n_pcr_values= */ 1,
6793 &pcr_policy_digest
);
6797 /* Store away this new variant */
6798 if (!GREEDY_REALLOC(pcr_policy_digest_variants
, n_pcr_policy_digest_variants
+ 1))
6801 pcr_policy_digest_variants
[n_pcr_policy_digest_variants
++] = pcr_policy_digest
;
6803 log_debug("Calculated PCR policy variant %zu for PCR %" PRIu32
, n_pcr_policy_digest_variants
, pcr
);
6806 assert_se(n_pcr_policy_digest_variants
>= 2);
6807 assert_se(n_pcr_policy_digest_variants
<= 8);
6809 /* Now combine all our variant into one OR policy */
6810 r
= tpm2_calculate_policy_or(
6811 pcr_policy_digest_variants
,
6812 n_pcr_policy_digest_variants
,
6813 &super_pcr_policy_digest
);
6817 log_debug("Combined %zu variants in OR policy.", n_pcr_policy_digest_variants
);
6820 *pcr_policy
= super_pcr_policy_digest
;
6824 int tpm2_policy_super_pcr(
6826 const Tpm2Handle
*session
,
6827 const Tpm2PCRPrediction
*prediction
,
6828 uint16_t algorithm
) {
6834 assert_se(prediction
);
6836 TPM2B_DIGEST previous_policy_digest
= TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
);
6838 uint32_t single_value_pcrs
= 0;
6840 /* Look for all PCRs that have only a singled allowed hash value, and synthesize a single PolicyPCR policy item for them */
6841 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6842 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6845 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6848 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6850 single_value_pcrs
|= UINT32_C(1) << pcr
;
6853 if (single_value_pcrs
!= 0) {
6854 TPML_PCR_SELECTION pcr_selection
;
6855 tpm2_tpml_pcr_selection_from_mask(single_value_pcrs
, algorithm
, &pcr_selection
);
6857 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6858 r
= tpm2_policy_pcr(
6862 ¤t_policy_digest
);
6866 previous_policy_digest
= *current_policy_digest
;
6869 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6872 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6875 n_branches
= ordered_set_size(prediction
->results
[pcr
]);
6876 if (n_branches
< 1 || n_branches
> 8)
6877 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "Number of variants per PCR not in range 1…8");
6879 if (n_branches
== 1) /* Single choice PCRs are already covered by the loop above */
6882 log_debug("Submitting PCR/OR policy for PCR %" PRIu32
, pcr
);
6884 TPML_PCR_SELECTION pcr_selection
;
6885 tpm2_tpml_pcr_selection_from_mask(UINT32_C(1) << pcr
, algorithm
, &pcr_selection
);
6887 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6888 r
= tpm2_policy_pcr(
6892 ¤t_policy_digest
);
6896 _cleanup_free_ TPM2B_DIGEST
*branches
= NULL
;
6897 branches
= new0(TPM2B_DIGEST
, n_branches
);
6901 Tpm2PCRPredictionResult
*banks
;
6903 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6904 TPM2B_DIGEST pcr_policy_digest
= previous_policy_digest
;
6906 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6910 /* Evolve it based on the expected PCR value for this PCR */
6911 r
= tpm2_calculate_policy_pcr(
6912 &TPM2_PCR_VALUE_MAKE(
6916 /* n_pcr_values= */ 1,
6917 &pcr_policy_digest
);
6921 branches
[i
++] = pcr_policy_digest
;
6924 assert_se(i
== n_branches
);
6926 current_policy_digest
= mfree(current_policy_digest
);
6932 ¤t_policy_digest
);
6936 previous_policy_digest
= *current_policy_digest
;
6942 void tpm2_pcrlock_policy_done(Tpm2PCRLockPolicy
*data
) {
6945 data
->prediction_json
= json_variant_unref(data
->prediction_json
);
6946 tpm2_pcr_prediction_done(&data
->prediction
);
6947 iovec_done(&data
->nv_handle
);
6948 iovec_done(&data
->nv_public
);
6949 iovec_done(&data
->srk_handle
);
6950 iovec_done(&data
->pin_public
);
6951 iovec_done(&data
->pin_private
);
6954 static int json_dispatch_tpm2_algorithm(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
6955 uint16_t *algorithm
= ASSERT_PTR(userdata
);
6958 r
= tpm2_hash_alg_from_string(json_variant_string(variant
));
6959 if (r
< 0 || tpm2_hash_algorithm_index(r
) == SIZE_MAX
)
6960 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid hash algorithm: %s", json_variant_string(variant
));
6966 int tpm2_pcrlock_search_file(const char *path
, FILE **ret_file
, char **ret_path
) {
6967 static const char search
[] =
6969 "/var/lib/systemd\0";
6974 path
= "pcrlock.json";
6976 r
= search_and_fopen_nulstr(path
, ret_file
? "re" : NULL
, NULL
, search
, ret_file
, ret_path
);
6978 return log_debug_errno(r
, "Failed to find TPM2 pcrlock policy file '%s': %m", path
);
6983 int tpm2_pcrlock_policy_from_json(
6985 Tpm2PCRLockPolicy
*ret_policy
) {
6987 /* We use a type check of _JSON_VARIANT_TYPE_INVALID for the integer fields to allow
6988 * json_dispatch_uint32() to parse strings as integers to work around the integer type weakness of
6990 JsonDispatch policy_dispatch
[] = {
6991 { "pcrBank", JSON_VARIANT_STRING
, json_dispatch_tpm2_algorithm
, offsetof(Tpm2PCRLockPolicy
, algorithm
), JSON_MANDATORY
},
6992 { "pcrValues", JSON_VARIANT_ARRAY
, json_dispatch_variant
, offsetof(Tpm2PCRLockPolicy
, prediction_json
), JSON_MANDATORY
},
6993 { "nvIndex", _JSON_VARIANT_TYPE_INVALID
, json_dispatch_uint32
, offsetof(Tpm2PCRLockPolicy
, nv_index
), JSON_MANDATORY
},
6994 { "nvHandle", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, nv_handle
), JSON_MANDATORY
},
6995 { "nvPublic", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, nv_public
), JSON_MANDATORY
},
6996 { "srkHandle", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, srk_handle
), JSON_MANDATORY
},
6997 { "pinPublic", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, pin_public
), JSON_MANDATORY
},
6998 { "pinPrivate", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, pin_private
), JSON_MANDATORY
},
7002 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy policy
= {};
7008 r
= json_dispatch(v
, policy_dispatch
, JSON_LOG
, &policy
);
7012 r
= tpm2_pcr_prediction_from_json(&policy
.prediction
, policy
.algorithm
, policy
.prediction_json
);
7016 *ret_policy
= TAKE_STRUCT(policy
);
7020 int tpm2_pcrlock_policy_load(
7022 Tpm2PCRLockPolicy
*ret_policy
) {
7024 _cleanup_free_
char *discovered_path
= NULL
;
7025 _cleanup_fclose_
FILE *f
= NULL
;
7028 r
= tpm2_pcrlock_search_file(path
, &f
, &discovered_path
);
7030 *ret_policy
= (Tpm2PCRLockPolicy
) {};
7034 return log_error_errno(r
, "Failed to load TPM2 pcrlock policy file: %m");
7036 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
7037 r
= json_parse_file(
7042 /* ret_line= */ NULL
,
7043 /* ret_column= */ NULL
);
7045 return log_error_errno(r
, "Failed to parse existing pcrlock policy file '%s': %m", discovered_path
);
7047 return tpm2_pcrlock_policy_from_json(v
, ret_policy
);
7050 static int pcrlock_policy_load_credential(
7052 const struct iovec
*data
,
7053 Tpm2PCRLockPolicy
*ret
) {
7055 _cleanup_free_
char *c
= NULL
;
7064 ascii_strlower(c
); /* Lowercase, to match what we did at encryption time */
7066 _cleanup_(iovec_done
) struct iovec decoded
= {};
7067 r
= decrypt_credential_and_warn(
7069 now(CLOCK_REALTIME
),
7070 /* tpm2_device= */ NULL
,
7071 /* tpm2_signature_path= */ NULL
,
7074 CREDENTIAL_ALLOW_NULL
,
7079 if (memchr(decoded
.iov_base
, 0, decoded
.iov_len
))
7080 return log_error_errno(r
, "Credential '%s' contains embedded NUL byte, refusing.", name
);
7082 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
7083 r
= json_parse(decoded
.iov_base
,
7086 /* ret_line= */ NULL
,
7087 /* ret_column= */ NULL
);
7089 return log_error_errno(r
, "Failed to parse pcrlock policy: %m");
7091 r
= tpm2_pcrlock_policy_from_json(v
, ret
);
7098 int tpm2_pcrlock_policy_from_credentials(
7099 const struct iovec
*srk
,
7100 const struct iovec
*nv
,
7101 Tpm2PCRLockPolicy
*ret
) {
7103 _cleanup_close_
int dfd
= -EBADF
;
7106 /* During boot we'll not have access to the pcrlock.json file in /var/. In order to support
7107 * pcrlock-bound root file systems we'll store a copy of the JSON data, wrapped in an (plaintext)
7108 * credential in the ESP or XBOOTLDR partition. There might be multiple of those however (because of
7109 * multi-boot), hence we use the SRK and NV data from the LUKS2 header as search key, and parse all
7110 * such JSON policies until we find a matching one. */
7112 const char *cp
= secure_getenv("SYSTEMD_ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY") ?: ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
;
7114 dfd
= open(cp
, O_CLOEXEC
|O_DIRECTORY
);
7116 if (errno
== ENOENT
) {
7117 log_debug("No encrypted system credentials passed.");
7121 return log_error_errno(errno
, "Failed to open system credentials directory.");
7124 _cleanup_free_ DirectoryEntries
*de
= NULL
;
7125 r
= readdir_all(dfd
, RECURSE_DIR_IGNORE_DOT
, &de
);
7127 return log_error_errno(r
, "Failed to enumerate system credentials: %m");
7129 FOREACH_ARRAY(i
, de
->entries
, de
->n_entries
) {
7130 _cleanup_(iovec_done
) struct iovec data
= {};
7131 struct dirent
*d
= *i
;
7133 if (!startswith_no_case(d
->d_name
, "pcrlock.")) /* VFAT is case-insensitive, hence don't be too strict here */
7136 r
= read_full_file_full(
7138 /* offset= */ UINT64_MAX
,
7139 /* size= */ CREDENTIAL_ENCRYPTED_SIZE_MAX
,
7140 READ_FULL_FILE_UNBASE64
|READ_FULL_FILE_FAIL_WHEN_LARGER
,
7141 /* bind_name= */ NULL
,
7142 (char**) &data
.iov_base
,
7147 log_warning_errno(r
, "Failed to read credentials file %s/%s, skipping: %m", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
7151 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy loaded_policy
= {};
7152 r
= pcrlock_policy_load_credential(
7157 log_warning_errno(r
, "Loading of pcrlock policy from credential '%s/%s' failed, skipping.", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
7161 if ((!srk
|| iovec_memcmp(srk
, &loaded_policy
.srk_handle
) == 0) &&
7162 (!nv
|| iovec_memcmp(nv
, &loaded_policy
.nv_handle
) == 0)) {
7163 *ret
= TAKE_STRUCT(loaded_policy
);
7168 log_info("No pcrlock policy found among system credentials.");
7169 *ret
= (Tpm2PCRLockPolicy
) {};
7173 int tpm2_load_public_key_file(const char *path
, TPM2B_PUBLIC
*ret
) {
7174 _cleanup_free_
char *device_key_buffer
= NULL
;
7175 TPM2B_PUBLIC device_key_public
= {};
7176 size_t device_key_buffer_size
;
7185 return log_debug_errno(r
, "TPM2 support not installed: %m");
7187 r
= read_full_file(path
, &device_key_buffer
, &device_key_buffer_size
);
7189 return log_error_errno(r
, "Failed to read device key from file '%s': %m", path
);
7192 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(
7193 (uint8_t*) device_key_buffer
,
7194 device_key_buffer_size
,
7196 &device_key_public
);
7197 if (rc
!= TSS2_RC_SUCCESS
)
7198 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
7199 "Could not unmarshal public key from file.");
7201 assert(offset
<= device_key_buffer_size
);
7202 if (offset
!= device_key_buffer_size
)
7203 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
7204 "Found %zu bytes of trailing garbage in public key file.",
7205 device_key_buffer_size
- offset
);
7207 *ret
= device_key_public
;
7211 int tpm2_hmac_key_from_pin(Tpm2Context
*c
, const Tpm2Handle
*session
, const TPM2B_AUTH
*pin
, Tpm2Handle
**ret
) {
7218 log_debug("Converting PIN into TPM2 HMAC-SHA256 object.");
7220 /* Load the PIN (which we have stored in the "auth" TPM2B_AUTH) into the TPM as an HMAC key so that
7221 * we can use it in a TPM2_PolicySigned() to write to the nvindex. For that we'll prep a pair of
7222 * TPM2B_PUBLIC and TPM2B_SENSITIVE that defines an HMAC-SHA256 keyed hash function, and initialize
7223 * it based on the provided PIN data. */
7225 TPM2B_PUBLIC auth_hmac_public
= {
7227 .type
= TPM2_ALG_KEYEDHASH
,
7228 .nameAlg
= TPM2_ALG_SHA256
,
7229 .objectAttributes
= TPMA_OBJECT_SIGN_ENCRYPT
,
7230 .parameters
.keyedHashDetail
.scheme
= {
7231 .scheme
= TPM2_ALG_HMAC
,
7232 .details
.hmac
.hashAlg
= TPM2_ALG_SHA256
,
7234 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
7238 TPM2B_SENSITIVE auth_hmac_private
= {
7240 .sensitiveType
= TPM2_ALG_KEYEDHASH
,
7241 .sensitive
.bits
.size
= pin
->size
,
7242 .seedValue
.size
= SHA256_DIGEST_SIZE
,
7246 /* Copy in the key data */
7247 memcpy_safe(auth_hmac_private
.sensitiveArea
.sensitive
.bits
.buffer
, pin
->buffer
, pin
->size
);
7249 /* NB: We initialize the seed of the TPMT_SENSITIVE structure to all zeroes, since we want a stable
7250 * "name" of the PIN object */
7252 /* Now calculate the "unique" field for the public area, based on the sensitive data, according to
7253 * the algorithm in the TPM2 spec, part 1, Section 27.5.3.2 */
7254 struct iovec sensitive_data
[] = {
7255 IOVEC_MAKE(auth_hmac_private
.sensitiveArea
.seedValue
.buffer
, auth_hmac_private
.sensitiveArea
.seedValue
.size
),
7256 IOVEC_MAKE(auth_hmac_private
.sensitiveArea
.sensitive
.bits
.buffer
, auth_hmac_private
.sensitiveArea
.sensitive
.bits
.size
),
7258 r
= tpm2_digest_many(
7259 auth_hmac_public
.publicArea
.nameAlg
,
7260 &auth_hmac_public
.publicArea
.unique
.keyedHash
,
7262 ELEMENTSOF(sensitive_data
),
7263 /* extend= */ false);
7267 /* And now load the public/private parts into the TPM and get a handle back */
7268 r
= tpm2_load_external(
7275 return log_error_errno(r
, "Failed to load PIN into TPM2: %m");
7281 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
7282 _cleanup_free_
char *s
= NULL
;
7284 FOREACH_PCR_IN_MASK(n
, mask
)
7285 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
7294 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
7295 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
7300 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
7301 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
7303 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
7306 r
= json_variant_new_integer(&e
, i
);
7310 r
= json_variant_append_array(&a
, e
);
7316 return json_variant_new_array(ret
, NULL
, 0);
7322 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
7326 if (!json_variant_is_array(v
))
7327 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
7329 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
7332 if (!json_variant_is_unsigned(e
))
7333 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
7335 u
= json_variant_unsigned(e
);
7336 if (u
>= TPM2_PCRS_MAX
)
7337 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR number out of range: %" PRIu64
, u
);
7339 mask
|= UINT32_C(1) << u
;
7348 int tpm2_make_luks2_json(
7350 uint32_t hash_pcr_mask
,
7352 const struct iovec
*pubkey
,
7353 uint32_t pubkey_pcr_mask
,
7354 uint16_t primary_alg
,
7355 const struct iovec
*blob
,
7356 const struct iovec
*policy_hash
,
7357 const struct iovec
*salt
,
7358 const struct iovec
*srk
,
7359 const struct iovec
*pcrlock_nv
,
7361 JsonVariant
**ret
) {
7363 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
7364 _cleanup_free_
char *keyslot_as_string
= NULL
;
7367 assert(iovec_is_valid(pubkey
));
7368 assert(iovec_is_valid(blob
));
7369 assert(iovec_is_valid(policy_hash
));
7371 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
7374 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
7378 if (pubkey_pcr_mask
!= 0) {
7379 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
7384 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
7385 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
7386 * object should use "_" rather than "-" in field names. */
7390 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
7391 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string
))),
7392 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_IOVEC_BASE64(blob
)),
7393 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj
)),
7394 JSON_BUILD_PAIR_CONDITION(pcr_bank
!= 0 && tpm2_hash_alg_to_string(pcr_bank
), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank
))),
7395 JSON_BUILD_PAIR_CONDITION(primary_alg
!= 0 && tpm2_asym_alg_to_string(primary_alg
), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg
))),
7396 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_IOVEC_HEX(policy_hash
)),
7397 JSON_BUILD_PAIR_CONDITION(FLAGS_SET(flags
, TPM2_FLAGS_USE_PIN
), "tpm2-pin", JSON_BUILD_BOOLEAN(true)),
7398 JSON_BUILD_PAIR_CONDITION(FLAGS_SET(flags
, TPM2_FLAGS_USE_PCRLOCK
), "tpm2_pcrlock", JSON_BUILD_BOOLEAN(true)),
7399 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj
)),
7400 JSON_BUILD_PAIR_CONDITION(iovec_is_set(pubkey
), "tpm2_pubkey", JSON_BUILD_IOVEC_BASE64(pubkey
)),
7401 JSON_BUILD_PAIR_CONDITION(iovec_is_set(salt
), "tpm2_salt", JSON_BUILD_IOVEC_BASE64(salt
)),
7402 JSON_BUILD_PAIR_CONDITION(iovec_is_set(srk
), "tpm2_srk", JSON_BUILD_IOVEC_BASE64(srk
)),
7403 JSON_BUILD_PAIR_CONDITION(iovec_is_set(pcrlock_nv
), "tpm2_pcrlock_nv", JSON_BUILD_IOVEC_BASE64(pcrlock_nv
))));
7413 int tpm2_parse_luks2_json(
7416 uint32_t *ret_hash_pcr_mask
,
7417 uint16_t *ret_pcr_bank
,
7418 struct iovec
*ret_pubkey
,
7419 uint32_t *ret_pubkey_pcr_mask
,
7420 uint16_t *ret_primary_alg
,
7421 struct iovec
*ret_blob
,
7422 struct iovec
*ret_policy_hash
,
7423 struct iovec
*ret_salt
,
7424 struct iovec
*ret_srk
,
7425 struct iovec
*ret_pcrlock_nv
,
7426 TPM2Flags
*ret_flags
) {
7428 _cleanup_(iovec_done
) struct iovec blob
= {}, policy_hash
= {}, pubkey
= {}, salt
= {}, srk
= {}, pcrlock_nv
= {};
7429 uint32_t hash_pcr_mask
= 0, pubkey_pcr_mask
= 0;
7430 uint16_t primary_alg
= TPM2_ALG_ECC
; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
7431 uint16_t pcr_bank
= UINT16_MAX
; /* default: pick automatically */
7432 int r
, keyslot
= -1;
7433 TPM2Flags flags
= 0;
7439 keyslot
= cryptsetup_get_keyslot_from_token(v
);
7441 /* Return a recognizable error when parsing this field, so that callers can handle parsing
7442 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
7444 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
7449 w
= json_variant_by_key(v
, "tpm2-pcrs");
7451 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
7453 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
7455 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
7457 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
7459 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
7461 /* The PCR bank field is optional */
7463 if (!json_variant_is_string(w
))
7464 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
7466 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
7468 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
7473 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
7474 * the algorithm was hardcoded to ECC. */
7475 w
= json_variant_by_key(v
, "tpm2-primary-alg");
7477 /* The primary key algorithm is optional */
7479 if (!json_variant_is_string(w
))
7480 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
7482 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
7484 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
7489 w
= json_variant_by_key(v
, "tpm2-blob");
7491 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
7493 r
= json_variant_unbase64_iovec(w
, &blob
);
7495 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
7497 w
= json_variant_by_key(v
, "tpm2-policy-hash");
7499 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
7501 r
= json_variant_unhex_iovec(w
, &policy_hash
);
7503 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
7505 w
= json_variant_by_key(v
, "tpm2-pin");
7507 if (!json_variant_is_boolean(w
))
7508 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
7510 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
7513 w
= json_variant_by_key(v
, "tpm2_pcrlock");
7515 if (!json_variant_is_boolean(w
))
7516 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 pclock policy is not a boolean.");
7518 SET_FLAG(flags
, TPM2_FLAGS_USE_PCRLOCK
, json_variant_boolean(w
));
7521 w
= json_variant_by_key(v
, "tpm2_salt");
7523 r
= json_variant_unbase64_iovec(w
, &salt
);
7525 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
7528 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
7530 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
7535 w
= json_variant_by_key(v
, "tpm2_pubkey");
7537 r
= json_variant_unbase64_iovec(w
, &pubkey
);
7539 return log_debug_errno(r
, "Failed to decode PCR public key.");
7540 } else if (pubkey_pcr_mask
!= 0)
7541 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Public key PCR mask set, but not public key included in JSON data, refusing.");
7543 w
= json_variant_by_key(v
, "tpm2_srk");
7545 r
= json_variant_unbase64_iovec(w
, &srk
);
7547 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
7550 w
= json_variant_by_key(v
, "tpm2_pcrlock_nv");
7552 r
= json_variant_unbase64_iovec(w
, &pcrlock_nv
);
7554 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_pcrlock_nv' field.");
7558 *ret_keyslot
= keyslot
;
7559 if (ret_hash_pcr_mask
)
7560 *ret_hash_pcr_mask
= hash_pcr_mask
;
7562 *ret_pcr_bank
= pcr_bank
;
7564 *ret_pubkey
= TAKE_STRUCT(pubkey
);
7565 if (ret_pubkey_pcr_mask
)
7566 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
7567 if (ret_primary_alg
)
7568 *ret_primary_alg
= primary_alg
;
7570 *ret_blob
= TAKE_STRUCT(blob
);
7571 if (ret_policy_hash
)
7572 *ret_policy_hash
= TAKE_STRUCT(policy_hash
);
7574 *ret_salt
= TAKE_STRUCT(salt
);
7576 *ret_srk
= TAKE_STRUCT(srk
);
7578 *ret_pcrlock_nv
= TAKE_STRUCT(pcrlock_nv
);
7584 int tpm2_hash_alg_to_size(uint16_t alg
) {
7588 case TPM2_ALG_SHA256
:
7590 case TPM2_ALG_SHA384
:
7592 case TPM2_ALG_SHA512
:
7595 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
7599 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
7603 case TPM2_ALG_SHA256
:
7605 case TPM2_ALG_SHA384
:
7607 case TPM2_ALG_SHA512
:
7610 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
7615 int tpm2_hash_alg_from_string(const char *alg
) {
7616 if (strcaseeq_ptr(alg
, "sha1"))
7617 return TPM2_ALG_SHA1
;
7618 if (strcaseeq_ptr(alg
, "sha256"))
7619 return TPM2_ALG_SHA256
;
7620 if (strcaseeq_ptr(alg
, "sha384"))
7621 return TPM2_ALG_SHA384
;
7622 if (strcaseeq_ptr(alg
, "sha512"))
7623 return TPM2_ALG_SHA512
;
7624 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm name '%s'", alg
);
7627 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
7634 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
7639 int tpm2_asym_alg_from_string(const char *alg
) {
7640 if (strcaseeq_ptr(alg
, "ecc"))
7641 return TPM2_ALG_ECC
;
7642 if (strcaseeq_ptr(alg
, "rsa"))
7643 return TPM2_ALG_RSA
;
7644 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown asymmetric algorithm name '%s'", alg
);
7647 const char *tpm2_sym_alg_to_string(uint16_t alg
) {
7654 log_debug("Unknown symmetric algorithm id 0x%" PRIx16
, alg
);
7659 int tpm2_sym_alg_from_string(const char *alg
) {
7661 if (strcaseeq_ptr(alg
, "aes"))
7662 return TPM2_ALG_AES
;
7664 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric algorithm name '%s'", alg
);
7667 const char *tpm2_sym_mode_to_string(uint16_t mode
) {
7682 log_debug("Unknown symmetric mode id 0x%" PRIx16
, mode
);
7687 int tpm2_sym_mode_from_string(const char *mode
) {
7689 if (strcaseeq_ptr(mode
, "ctr"))
7690 return TPM2_ALG_CTR
;
7691 if (strcaseeq_ptr(mode
, "ofb"))
7692 return TPM2_ALG_OFB
;
7693 if (strcaseeq_ptr(mode
, "cbc"))
7694 return TPM2_ALG_CBC
;
7695 if (strcaseeq_ptr(mode
, "cfb"))
7696 return TPM2_ALG_CFB
;
7697 if (strcaseeq_ptr(mode
, "ecb"))
7698 return TPM2_ALG_ECB
;
7700 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric mode name '%s'", mode
);
7703 Tpm2Support
tpm2_support(void) {
7704 Tpm2Support support
= TPM2_SUPPORT_NONE
;
7707 if (detect_container() <= 0) {
7708 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
7709 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
7710 * let's assume containers never have a TPM, at least for now. */
7712 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
7715 log_debug_errno(r
, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
7716 } else if (r
== 0) /* populated! */
7717 support
|= TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_DRIVER
;
7719 /* If the directory exists but is empty, we know the subsystem is enabled but no
7720 * driver has been loaded yet. */
7721 support
|= TPM2_SUPPORT_SUBSYSTEM
;
7725 support
|= TPM2_SUPPORT_FIRMWARE
;
7728 support
|= TPM2_SUPPORT_SYSTEM
;
7732 support
|= TPM2_SUPPORT_LIBRARIES
;
7739 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
7740 TPMI_ALG_HASH default_hash
= 0;
7741 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
7743 default_hash
= v
->hash
;
7747 if (default_hash
!= 0)
7748 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
7750 v
->hash
= default_hash
;
7754 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
7755 * parse_*_argument() functions. */
7757 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
7759 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
7760 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
7761 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
7763 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
7764 * tpm2_parse_pcr_argument_append(). */
7765 int tpm2_parse_pcr_argument(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
7770 assert(ret_pcr_values
);
7771 assert(ret_n_pcr_values
);
7773 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
7774 size_t n_pcr_values
= 0;
7775 r
= tpm2_pcr_values_from_string(arg
, &pcr_values
, &n_pcr_values
);
7777 return log_error_errno(r
, "Could not parse PCR values from '%s': %m", arg
);
7779 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
7781 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
7783 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
7784 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
7786 *ret_pcr_values
= TAKE_PTR(pcr_values
);
7787 *ret_n_pcr_values
= n_pcr_values
;
7791 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7795 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
7796 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
7799 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
7800 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
7801 * algorithm check applied again (in case either the previous or current array had no default hash
7802 * algorithm), and then the resulting array is sorted and rechecked for validity. */
7803 int tpm2_parse_pcr_argument_append(const char *arg
, Tpm2PCRValue
**pcr_values
, size_t *n_pcr_values
) {
7809 assert(n_pcr_values
);
7811 _cleanup_free_ Tpm2PCRValue
*more_pcr_values
= NULL
;
7812 size_t n_more_pcr_values
;
7813 r
= tpm2_parse_pcr_argument(arg
, &more_pcr_values
, &n_more_pcr_values
);
7817 /* If we got previous values, append them. */
7818 if (*pcr_values
&& !GREEDY_REALLOC_APPEND(more_pcr_values
, n_more_pcr_values
, *pcr_values
, *n_pcr_values
))
7821 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values
, n_more_pcr_values
);
7823 tpm2_sort_pcr_values(more_pcr_values
, n_more_pcr_values
);
7825 if (!tpm2_pcr_values_valid(more_pcr_values
, n_more_pcr_values
))
7826 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
7828 SWAP_TWO(*pcr_values
, more_pcr_values
);
7829 *n_pcr_values
= n_more_pcr_values
;
7833 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7837 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
7838 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
7839 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
7840 * UINT32_MAX, and or-ing the mask otherwise. */
7841 int tpm2_parse_pcr_argument_to_mask(const char *arg
, uint32_t *ret_mask
) {
7843 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
7844 size_t n_pcr_values
;
7850 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
7854 if (n_pcr_values
== 0) {
7855 /* This retains the previous behavior of clearing the mask if the arg is empty */
7861 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
7863 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
7866 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
7869 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
7871 return log_error_errno(r
, "Could not get pcr values mask: %m");
7873 if (*ret_mask
== UINT32_MAX
)
7874 *ret_mask
= new_mask
;
7876 *ret_mask
|= new_mask
;
7880 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7884 int tpm2_load_pcr_signature(const char *path
, JsonVariant
**ret
) {
7885 _cleanup_strv_free_
char **search
= NULL
;
7886 _cleanup_free_
char *discovered_path
= NULL
;
7887 _cleanup_fclose_
FILE *f
= NULL
;
7890 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
7891 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7893 search
= strv_new(CONF_PATHS("systemd"));
7895 return log_oom_debug();
7898 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
7899 * this case include /.extra/ in the search path, but only in this case, and if we run in the
7900 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
7902 path
= "tpm2-pcr-signature.json";
7905 if (strv_extend(&search
, "/.extra") < 0)
7906 return log_oom_debug();
7909 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
7911 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
7913 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
7915 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
7920 int tpm2_load_pcr_public_key(const char *path
, void **ret_pubkey
, size_t *ret_pubkey_size
) {
7921 _cleanup_free_
char *discovered_path
= NULL
;
7922 _cleanup_fclose_
FILE *f
= NULL
;
7925 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
7926 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7929 path
= "tpm2-pcr-public-key.pem";
7931 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
7933 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
7935 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
7937 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
7942 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
7945 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
7946 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
7947 * I found the wikipedia entry relevant and it contains links to
7949 * - https://en.wikipedia.org/wiki/PBKDF2
7950 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
7952 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
7956 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
7958 _cleanup_(erase_and_freep
) uint8_t *buffer
= NULL
;
7959 uint8_t u
[SHA256_DIGEST_SIZE
];
7961 /* To keep this simple, since derived KeyLen (dkLen in docs)
7962 * Is the same as the hash output, we don't need multiple
7963 * blocks. Part of the algorithm is to add the block count
7964 * in, but this can be hardcoded to 1.
7966 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
7969 assert (saltlen
> 0);
7970 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
7971 assert (passlen
> 0);
7974 * Build a buffer of salt + block_cnt and hmac_sha256 it we
7975 * do this as we don't have a context builder for HMAC_SHA256.
7977 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
7981 memcpy(buffer
, salt
, saltlen
);
7982 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
7984 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
7986 /* dk needs to be an unmodified u as u gets modified in the loop */
7987 memcpy(ret_key
, u
, SHA256_DIGEST_SIZE
);
7988 uint8_t *dk
= ret_key
;
7990 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
7991 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
7993 for (size_t j
=0; j
< sizeof(u
); j
++)
8000 static const char* const tpm2_pcr_index_table
[_TPM2_PCR_INDEX_MAX_DEFINED
] = {
8001 [TPM2_PCR_PLATFORM_CODE
] = "platform-code",
8002 [TPM2_PCR_PLATFORM_CONFIG
] = "platform-config",
8003 [TPM2_PCR_EXTERNAL_CODE
] = "external-code",
8004 [TPM2_PCR_EXTERNAL_CONFIG
] = "external-config",
8005 [TPM2_PCR_BOOT_LOADER_CODE
] = "boot-loader-code",
8006 [TPM2_PCR_BOOT_LOADER_CONFIG
] = "boot-loader-config",
8007 [TPM2_PCR_HOST_PLATFORM
] = "host-platform",
8008 [TPM2_PCR_SECURE_BOOT_POLICY
] = "secure-boot-policy",
8009 [TPM2_PCR_KERNEL_INITRD
] = "kernel-initrd",
8010 [TPM2_PCR_IMA
] = "ima",
8011 [TPM2_PCR_KERNEL_BOOT
] = "kernel-boot",
8012 [TPM2_PCR_KERNEL_CONFIG
] = "kernel-config",
8013 [TPM2_PCR_SYSEXTS
] = "sysexts",
8014 [TPM2_PCR_SHIM_POLICY
] = "shim-policy",
8015 [TPM2_PCR_SYSTEM_IDENTITY
] = "system-identity",
8016 [TPM2_PCR_DEBUG
] = "debug",
8017 [TPM2_PCR_APPLICATION_SUPPORT
] = "application-support",
8020 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index
, int, TPM2_PCRS_MAX
- 1);
8021 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index
, int);