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 static void *libtss2_esys_dl
= NULL
;
42 static void *libtss2_rc_dl
= NULL
;
43 static void *libtss2_mu_dl
= NULL
;
45 static DLSYM_FUNCTION(Esys_Create
);
46 static DLSYM_FUNCTION(Esys_CreateLoaded
);
47 static DLSYM_FUNCTION(Esys_CreatePrimary
);
48 static DLSYM_FUNCTION(Esys_EvictControl
);
49 static DLSYM_FUNCTION(Esys_Finalize
);
50 static DLSYM_FUNCTION(Esys_FlushContext
);
51 static DLSYM_FUNCTION(Esys_Free
);
52 static DLSYM_FUNCTION(Esys_GetCapability
);
53 static DLSYM_FUNCTION(Esys_GetRandom
);
54 static DLSYM_FUNCTION(Esys_Import
);
55 static DLSYM_FUNCTION(Esys_Initialize
);
56 static DLSYM_FUNCTION(Esys_Load
);
57 static DLSYM_FUNCTION(Esys_LoadExternal
);
58 static DLSYM_FUNCTION(Esys_NV_DefineSpace
);
59 static DLSYM_FUNCTION(Esys_NV_UndefineSpace
);
60 static DLSYM_FUNCTION(Esys_NV_Write
);
61 static DLSYM_FUNCTION(Esys_PCR_Extend
);
62 static DLSYM_FUNCTION(Esys_PCR_Read
);
63 static DLSYM_FUNCTION(Esys_PolicyAuthValue
);
64 static DLSYM_FUNCTION(Esys_PolicyAuthorize
);
65 static DLSYM_FUNCTION(Esys_PolicyAuthorizeNV
);
66 static DLSYM_FUNCTION(Esys_PolicyGetDigest
);
67 static DLSYM_FUNCTION(Esys_PolicyOR
);
68 static DLSYM_FUNCTION(Esys_PolicyPCR
);
69 static DLSYM_FUNCTION(Esys_PolicySigned
);
70 static DLSYM_FUNCTION(Esys_ReadPublic
);
71 static DLSYM_FUNCTION(Esys_StartAuthSession
);
72 static DLSYM_FUNCTION(Esys_Startup
);
73 static DLSYM_FUNCTION(Esys_TestParms
);
74 static DLSYM_FUNCTION(Esys_TR_Close
);
75 static DLSYM_FUNCTION(Esys_TR_Deserialize
);
76 static DLSYM_FUNCTION(Esys_TR_FromTPMPublic
);
77 static DLSYM_FUNCTION(Esys_TR_GetName
);
78 static DLSYM_FUNCTION(Esys_TR_GetTpmHandle
);
79 static DLSYM_FUNCTION(Esys_TR_Serialize
);
80 static DLSYM_FUNCTION(Esys_TR_SetAuth
);
81 static DLSYM_FUNCTION(Esys_TRSess_GetAttributes
);
82 static DLSYM_FUNCTION(Esys_TRSess_GetNonceTPM
);
83 static DLSYM_FUNCTION(Esys_TRSess_SetAttributes
);
84 static DLSYM_FUNCTION(Esys_Unseal
);
85 static DLSYM_FUNCTION(Esys_VerifySignature
);
87 static DLSYM_FUNCTION(Tss2_MU_TPM2_CC_Marshal
);
88 static DLSYM_FUNCTION(Tss2_MU_TPM2_HANDLE_Marshal
);
89 static DLSYM_FUNCTION(Tss2_MU_TPM2B_DIGEST_Marshal
);
90 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal
);
91 static DLSYM_FUNCTION(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal
);
92 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NAME_Marshal
);
93 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Marshal
);
94 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PRIVATE_Unmarshal
);
95 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Marshal
);
96 static DLSYM_FUNCTION(Tss2_MU_TPM2B_PUBLIC_Unmarshal
);
97 static DLSYM_FUNCTION(Tss2_MU_TPM2B_SENSITIVE_Marshal
);
98 static DLSYM_FUNCTION(Tss2_MU_TPML_PCR_SELECTION_Marshal
);
99 static DLSYM_FUNCTION(Tss2_MU_TPMS_NV_PUBLIC_Marshal
);
100 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Marshal
);
101 static DLSYM_FUNCTION(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal
);
102 static DLSYM_FUNCTION(Tss2_MU_TPMS_ECC_POINT_Marshal
);
103 static DLSYM_FUNCTION(Tss2_MU_TPMT_HA_Marshal
);
104 static DLSYM_FUNCTION(Tss2_MU_TPMT_PUBLIC_Marshal
);
105 static DLSYM_FUNCTION(Tss2_MU_UINT32_Marshal
);
107 static DLSYM_FUNCTION(Tss2_RC_Decode
);
109 int dlopen_tpm2(void) {
112 r
= dlopen_many_sym_or_warn(
113 &libtss2_esys_dl
, "libtss2-esys.so.0", LOG_DEBUG
,
114 DLSYM_ARG(Esys_Create
),
115 DLSYM_ARG(Esys_CreateLoaded
),
116 DLSYM_ARG(Esys_CreatePrimary
),
117 DLSYM_ARG(Esys_EvictControl
),
118 DLSYM_ARG(Esys_Finalize
),
119 DLSYM_ARG(Esys_FlushContext
),
120 DLSYM_ARG(Esys_Free
),
121 DLSYM_ARG(Esys_GetCapability
),
122 DLSYM_ARG(Esys_GetRandom
),
123 DLSYM_ARG(Esys_Import
),
124 DLSYM_ARG(Esys_Initialize
),
125 DLSYM_ARG(Esys_Load
),
126 DLSYM_ARG(Esys_LoadExternal
),
127 DLSYM_ARG(Esys_NV_DefineSpace
),
128 DLSYM_ARG(Esys_NV_UndefineSpace
),
129 DLSYM_ARG(Esys_NV_Write
),
130 DLSYM_ARG(Esys_PCR_Extend
),
131 DLSYM_ARG(Esys_PCR_Read
),
132 DLSYM_ARG(Esys_PolicyAuthValue
),
133 DLSYM_ARG(Esys_PolicyAuthorize
),
134 DLSYM_ARG(Esys_PolicyAuthorizeNV
),
135 DLSYM_ARG(Esys_PolicyGetDigest
),
136 DLSYM_ARG(Esys_PolicyOR
),
137 DLSYM_ARG(Esys_PolicyPCR
),
138 DLSYM_ARG(Esys_PolicySigned
),
139 DLSYM_ARG(Esys_ReadPublic
),
140 DLSYM_ARG(Esys_StartAuthSession
),
141 DLSYM_ARG(Esys_Startup
),
142 DLSYM_ARG(Esys_TestParms
),
143 DLSYM_ARG(Esys_TR_Close
),
144 DLSYM_ARG(Esys_TR_Deserialize
),
145 DLSYM_ARG(Esys_TR_FromTPMPublic
),
146 DLSYM_ARG(Esys_TR_GetName
),
147 DLSYM_ARG(Esys_TR_Serialize
),
148 DLSYM_ARG(Esys_TR_SetAuth
),
149 DLSYM_ARG(Esys_TRSess_GetAttributes
),
150 DLSYM_ARG(Esys_TRSess_GetNonceTPM
),
151 DLSYM_ARG(Esys_TRSess_SetAttributes
),
152 DLSYM_ARG(Esys_Unseal
),
153 DLSYM_ARG(Esys_VerifySignature
));
157 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
158 * version of 2.4.0 this sym can be moved up to the normal list above. */
159 r
= dlsym_many_or_warn(libtss2_esys_dl
, LOG_DEBUG
, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle
));
161 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
163 r
= dlopen_many_sym_or_warn(
164 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
165 DLSYM_ARG(Tss2_RC_Decode
));
169 return dlopen_many_sym_or_warn(
170 &libtss2_mu_dl
, "libtss2-mu.so.0", LOG_DEBUG
,
171 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal
),
172 DLSYM_ARG(Tss2_MU_TPM2_HANDLE_Marshal
),
173 DLSYM_ARG(Tss2_MU_TPM2B_DIGEST_Marshal
),
174 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal
),
175 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal
),
176 DLSYM_ARG(Tss2_MU_TPM2B_NAME_Marshal
),
177 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal
),
178 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal
),
179 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal
),
180 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal
),
181 DLSYM_ARG(Tss2_MU_TPM2B_SENSITIVE_Marshal
),
182 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal
),
183 DLSYM_ARG(Tss2_MU_TPMS_NV_PUBLIC_Marshal
),
184 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Marshal
),
185 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal
),
186 DLSYM_ARG(Tss2_MU_TPMS_ECC_POINT_Marshal
),
187 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal
),
188 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal
),
189 DLSYM_ARG(Tss2_MU_UINT32_Marshal
));
192 void Esys_Freep(void *p
) {
194 sym_Esys_Free(*(void**) p
);
197 /* Get a specific TPM capability (or capabilities).
199 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
200 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
201 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
202 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
204 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
205 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
206 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
207 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
208 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
209 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
210 * capability category may have more specific requirements than described here; see the spec for exact
212 static int tpm2_get_capability(
217 TPMU_CAPABILITIES
*ret_capability_data
) {
219 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
225 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
226 capability
, property
, count
);
228 rc
= sym_Esys_GetCapability(
238 if (rc
== TPM2_RC_VALUE
)
239 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
),
240 "Requested TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" apparently doesn't exist: %s",
241 capability
, property
, sym_Tss2_RC_Decode(rc
));
242 if (rc
!= TSS2_RC_SUCCESS
)
243 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
244 "Failed to get TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
": %s",
245 capability
, property
, sym_Tss2_RC_Decode(rc
));
246 if (capabilities
->capability
!= capability
)
247 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
248 "TPM provided wrong capability: 0x%04" PRIx32
" instead of 0x%04" PRIx32
".",
249 capabilities
->capability
, capability
);
251 if (ret_capability_data
)
252 *ret_capability_data
= capabilities
->data
;
254 return more
== TPM2_YES
;
257 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
259 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
260 TPMU_CAPABILITIES capability
;
265 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
266 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
267 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
268 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
269 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
270 * changed while we are performing some operation, it's reasonable to assume it will break us even if
271 * we don't cache the algorithms, thus they should be "safe" to cache. */
272 TPM2_ALG_ID current_alg
= TPM2_ALG_FIRST
;
274 r
= tpm2_get_capability(
277 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
283 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
285 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
286 * there are no more. */
287 assert(algorithms
.count
> 0);
289 if (!GREEDY_REALLOC_APPEND(
290 c
->capability_algorithms
,
291 c
->n_capability_algorithms
,
292 algorithms
.algProperties
,
294 return log_oom_debug();
299 /* Set current_alg to alg id after last alg id the TPM provided */
300 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
303 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
304 * while running, but that would be crazy, so let's hope it is not possible. */
305 TPM2_CC current_cc
= TPM2_CC_FIRST
;
307 r
= tpm2_get_capability(
316 TPML_CCA commands
= capability
.command
;
318 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
319 * there are no more. */
320 assert(commands
.count
> 0);
322 if (!GREEDY_REALLOC_APPEND(
323 c
->capability_commands
,
324 c
->n_capability_commands
,
325 commands
.commandAttributes
,
327 return log_oom_debug();
332 /* Set current_cc to index after last cc the TPM provided */
333 current_cc
= TPMA_CC_TO_TPM2_CC(commands
.commandAttributes
[commands
.count
- 1]) + 1;
336 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
337 * while running, but that would be crazy, so let's hope it is not possible. */
338 TPM2_ECC_CURVE current_ecc_curve
= TPM2_ECC_NONE
;
340 r
= tpm2_get_capability(
346 if (r
== -ENXIO
) /* If the TPM doesn't support ECC, it might return TPM2_RC_VALUE rather than capability.eccCurves == 0 */
351 TPML_ECC_CURVE ecc_curves
= capability
.eccCurves
;
353 /* ECC support isn't required */
354 if (ecc_curves
.count
== 0)
357 if (!GREEDY_REALLOC_APPEND(
358 c
->capability_ecc_curves
,
359 c
->n_capability_ecc_curves
,
360 ecc_curves
.eccCurves
,
362 return log_oom_debug();
367 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
368 current_ecc_curve
= ecc_curves
.eccCurves
[ecc_curves
.count
- 1] + 1;
371 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
372 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
373 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
374 * safely assume the TPM PCR allocation will not change while we are using it. */
375 r
= tpm2_get_capability(
384 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
385 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
386 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
387 * this command with the full PCR allocation and moreData will be NO." */
388 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
389 c
->capability_pcrs
= capability
.assignedPCR
;
394 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
395 * TPMA_ALGORITHM is provided, otherwise false. */
396 static bool tpm2_get_capability_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
, TPMA_ALGORITHM
*ret
) {
399 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
400 if (alg_prop
->alg
== alg
) {
402 *ret
= alg_prop
->algProperties
;
406 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
413 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
414 return tpm2_get_capability_alg(c
, alg
, NULL
);
417 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
418 * otherwise false. */
419 static bool tpm2_get_capability_command(Tpm2Context
*c
, TPM2_CC command
, TPMA_CC
*ret
) {
422 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
423 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
429 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
436 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
437 return tpm2_get_capability_command(c
, command
, NULL
);
440 /* Returns true if the TPM supports the ECC curve, otherwise false. */
441 bool tpm2_supports_ecc_curve(Tpm2Context
*c
, TPM2_ECC_CURVE ecc_curve
) {
444 FOREACH_ARRAY(curve
, c
->capability_ecc_curves
, c
->n_capability_ecc_curves
)
445 if (*curve
== ecc_curve
)
448 log_debug("TPM does not support ECC curve 0x%" PRIx16
".", ecc_curve
);
452 /* Query the TPM for populated handles.
454 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
455 * contain only populated handle addresses (which might not include the requested handle). The number of
456 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
457 * range (i.e. handle & 0xff000000).
459 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
460 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
461 static int tpm2_get_capability_handles(
465 TPM2_HANDLE
**ret_handles
,
466 size_t *ret_n_handles
) {
468 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
469 size_t n_handles
= 0;
470 TPM2_HANDLE current
= start
;
475 assert(ret_n_handles
);
477 max
= MIN(max
, UINT32_MAX
);
480 TPMU_CAPABILITIES capability
;
481 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
485 TPML_HANDLE handle_list
= capability
.handles
;
486 if (handle_list
.count
== 0)
489 assert(handle_list
.count
<= max
);
491 if (n_handles
> SIZE_MAX
- handle_list
.count
)
492 return log_oom_debug();
494 if (!GREEDY_REALLOC_APPEND(handles
, n_handles
, handle_list
.handle
, handle_list
.count
))
495 return log_oom_debug();
497 max
-= handle_list
.count
;
499 /* Update current to the handle index after the last handle in the list. */
500 current
= handles
[n_handles
- 1] + 1;
503 /* No more handles in this range. */
507 *ret_handles
= TAKE_PTR(handles
);
508 *ret_n_handles
= n_handles
;
513 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
514 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
516 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
517 static int tpm2_get_capability_handle(Tpm2Context
*c
, TPM2_HANDLE handle
) {
518 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
519 size_t n_handles
= 0;
522 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
526 return n_handles
== 0 ? false : handles
[0] == handle
;
529 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
530 bool tpm2_test_parms(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, const TPMU_PUBLIC_PARMS
*parms
) {
536 TPMT_PUBLIC_PARMS parameters
= {
538 .parameters
= *parms
,
541 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
542 if (rc
!= TSS2_RC_SUCCESS
)
543 /* The spec says if the parms are not supported the TPM returns "...the appropriate
544 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
545 * unmarshaling errors, instead of checking for them all here, let's just assume any error
546 * indicates unsupported parms, and log the specific error text. */
547 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc
));
549 return rc
== TSS2_RC_SUCCESS
;
552 static bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
556 return tpm2_test_parms(c
, public->type
, &public->parameters
);
559 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
563 TPMU_PUBLIC_PARMS parms
= {
564 .symDetail
.sym
= *parameters
,
567 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
570 static bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
574 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
575 * functionally identical. */
576 TPMT_SYM_DEF_OBJECT object
= {
577 .algorithm
= parameters
->algorithm
,
578 .keyBits
= parameters
->keyBits
,
579 .mode
= parameters
->mode
,
582 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
585 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
590 sym_Esys_Finalize(&c
->esys_context
);
592 c
->tcti_context
= mfree(c
->tcti_context
);
593 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
595 c
->capability_algorithms
= mfree(c
->capability_algorithms
);
596 c
->capability_commands
= mfree(c
->capability_commands
);
597 c
->capability_ecc_curves
= mfree(c
->capability_ecc_curves
);
602 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
604 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
605 .algorithm
= TPM2_ALG_AES
,
607 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
610 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
611 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
617 context
= new(Tpm2Context
, 1);
619 return log_oom_debug();
621 *context
= (Tpm2Context
) {
627 return log_debug_errno(r
, "TPM2 support not installed: %m");
630 device
= secure_getenv("SYSTEMD_TPM2_DEVICE");
632 /* Setting the env var to an empty string forces tpm2-tss' own device picking
633 * logic to be used. */
634 device
= empty_to_null(device
);
636 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
637 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
638 * might be used and we really don't want that, since it is a system service and that creates
639 * various ordering issues/deadlocks during early boot. */
640 device
= "device:/dev/tpmrm0";
644 const char *param
, *driver
, *fn
;
645 const TSS2_TCTI_INFO
* info
;
646 TSS2_TCTI_INFO_FUNC func
;
649 param
= strchr(device
, ':');
651 /* Syntax #1: Pair of driver string and arbitrary parameter */
652 driver
= strndupa_safe(device
, param
- device
);
654 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
657 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
658 /* Syntax #2: TPM device node */
662 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
664 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
666 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
668 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
669 if (!filename_is_valid(fn
))
670 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name '%s' not valid, refusing.", driver
);
672 context
->tcti_dl
= dlopen(fn
, RTLD_NOW
);
673 if (!context
->tcti_dl
)
674 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to load %s: %s", fn
, dlerror());
676 log_debug("Loaded '%s' via dlopen()", fn
);
678 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
680 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
681 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
686 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
688 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
690 rc
= info
->init(NULL
, &sz
, NULL
);
691 if (rc
!= TPM2_RC_SUCCESS
)
692 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
693 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
695 context
->tcti_context
= malloc0(sz
);
696 if (!context
->tcti_context
)
697 return log_oom_debug();
699 rc
= info
->init(context
->tcti_context
, &sz
, param
);
700 if (rc
!= TPM2_RC_SUCCESS
)
701 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
702 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
705 rc
= sym_Esys_Initialize(&context
->esys_context
, context
->tcti_context
, NULL
);
706 if (rc
!= TSS2_RC_SUCCESS
)
707 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
708 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc
));
710 rc
= sym_Esys_Startup(context
->esys_context
, TPM2_SU_CLEAR
);
711 if (rc
== TPM2_RC_INITIALIZE
)
712 log_debug("TPM already started up.");
713 else if (rc
== TSS2_RC_SUCCESS
)
714 log_debug("TPM successfully started up.");
716 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
717 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
719 r
= tpm2_cache_capabilities(context
);
721 return log_debug_errno(r
, "Failed to cache TPM capabilities: %m");
723 /* We require AES and CFB support for session encryption. */
724 if (!tpm2_supports_alg(context
, TPM2_ALG_AES
))
725 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES.");
727 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
728 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support CFB.");
730 if (!tpm2_supports_tpmt_sym_def(context
, &SESSION_TEMPLATE_SYM_AES_128_CFB
))
731 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES-128-CFB.");
733 *ret_context
= TAKE_PTR(context
);
738 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
741 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
744 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
745 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
746 * as removing its corresponding handle from the actual TPM. */
748 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
750 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
751 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
752 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
753 * directly affects us; for example the src/test/test-tpm2.c test function
754 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
755 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
756 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
757 * references will be cleaned up when we free our ESYS_CONTEXT.
759 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
760 rc
= TSS2_RC_SUCCESS
; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
761 if (rc
!= TSS2_RC_SUCCESS
)
762 /* We ignore failures here (besides debug logging), since this is called in error paths,
763 * where we cannot do anything about failures anymore. And when it is called in successful
764 * codepaths by this time we already did what we wanted to do, and got the results we wanted
765 * so there's no reason to make this fail more loudly than necessary. */
766 log_debug("Failed to %s TPM handle, ignoring: %s", flush
? "flush" : "close", sym_Tss2_RC_Decode(rc
));
769 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
773 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
775 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
777 return mfree(handle
);
780 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
781 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
785 handle
= new(Tpm2Handle
, 1);
787 return log_oom_debug();
789 *handle
= (Tpm2Handle
) {
790 .tpm2_context
= tpm2_context_ref(context
),
791 .esys_handle
= ESYS_TR_NONE
,
795 *ret_handle
= TAKE_PTR(handle
);
800 static int tpm2_read_public(
802 const Tpm2Handle
*session
,
803 const Tpm2Handle
*handle
,
804 TPM2B_PUBLIC
**ret_public
,
805 TPM2B_NAME
**ret_name
,
806 TPM2B_NAME
**ret_qname
) {
813 rc
= sym_Esys_ReadPublic(
816 session
? session
->esys_handle
: ESYS_TR_NONE
,
822 if (rc
!= TSS2_RC_SUCCESS
)
823 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
824 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
829 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
830 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
831 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
832 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
834 int tpm2_index_to_handle(
837 const Tpm2Handle
*session
,
838 TPM2B_PUBLIC
**ret_public
,
839 TPM2B_NAME
**ret_name
,
840 TPM2B_NAME
**ret_qname
,
841 Tpm2Handle
**ret_handle
) {
848 /* Only allow persistent, transient, or NV index handle types. */
849 switch (TPM2_HANDLE_TYPE(index
)) {
850 case TPM2_HT_PERSISTENT
:
851 case TPM2_HT_NV_INDEX
:
852 case TPM2_HT_TRANSIENT
:
855 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
856 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
857 "Invalid handle 0x%08" PRIx32
" (in PCR range).", index
);
858 case TPM2_HT_HMAC_SESSION
:
859 case TPM2_HT_POLICY_SESSION
:
860 /* Session indexes are only used internally by tpm2-tss (or lower code) */
861 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
862 "Invalid handle 0x%08" PRIx32
" (in session range).", index
);
863 case TPM2_HT_PERMANENT
:
864 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
865 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
866 "Invalid handle 0x%08" PRIx32
" (in permanent range).", index
);
868 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
869 "Invalid handle 0x%08" PRIx32
" (in unknown range).", index
);
872 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
873 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
874 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
875 if (TPM2_HANDLE_TYPE(index
) != TPM2_HT_TRANSIENT
) { // FIXME: once kernel bug is fixed, check transient handles too
876 r
= tpm2_get_capability_handle(c
, index
);
880 log_debug("TPM handle 0x%08" PRIx32
" not populated.", index
);
893 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
894 r
= tpm2_handle_new(c
, &handle
);
898 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
899 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
900 handle
->flush
= false;
902 rc
= sym_Esys_TR_FromTPMPublic(
905 session
? session
->esys_handle
: ESYS_TR_NONE
,
908 &handle
->esys_handle
);
909 if (rc
!= TSS2_RC_SUCCESS
)
910 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
911 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
913 if (ret_public
|| ret_name
|| ret_qname
) {
914 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
920 *ret_handle
= TAKE_PTR(handle
);
925 /* Get the handle index for the provided Tpm2Handle. */
926 int tpm2_index_from_handle(Tpm2Context
*c
, const Tpm2Handle
*handle
, TPM2_HANDLE
*ret_index
) {
933 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
934 * version of 2.4.0 this check can be removed. */
935 if (!sym_Esys_TR_GetTpmHandle
)
936 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
937 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
939 rc
= sym_Esys_TR_GetTpmHandle(c
->esys_context
, handle
->esys_handle
, ret_index
);
940 if (rc
!= TSS2_RC_SUCCESS
)
941 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
942 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc
));
947 /* Copy an object in the TPM at a transient handle to a persistent handle.
949 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
950 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
951 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
954 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
955 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
956 * at the requested persistent handle index (or the first available if none was requested).
958 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
959 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
960 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
961 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
962 * memory for persistent storage. The persistent handle is only provided when returning 1. */
963 static int tpm2_persist_handle(
965 const Tpm2Handle
*transient_handle
,
966 const Tpm2Handle
*session
,
967 TPMI_DH_PERSISTENT persistent_handle_index
,
968 Tpm2Handle
**ret_persistent_handle
) {
970 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
971 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
972 TPMI_DH_PERSISTENT first
= UINT32_C(0x81000000), last
= UINT32_C(0x81ffffff);
977 assert(transient_handle
);
979 /* If persistent handle index specified, only try that. */
980 if (persistent_handle_index
!= 0) {
981 if (TPM2_HANDLE_TYPE(persistent_handle_index
) != TPM2_HT_PERSISTENT
)
982 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
983 "Handle not in persistent range: 0x%x", persistent_handle_index
);
985 first
= last
= persistent_handle_index
;
988 for (TPMI_DH_PERSISTENT requested
= first
; requested
<= last
; requested
++) {
989 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*persistent_handle
= NULL
;
990 r
= tpm2_handle_new(c
, &persistent_handle
);
994 /* Since this is a persistent handle, don't flush it. */
995 persistent_handle
->flush
= false;
997 rc
= sym_Esys_EvictControl(
1000 transient_handle
->esys_handle
,
1001 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
1005 &persistent_handle
->esys_handle
);
1006 if (rc
== TSS2_RC_SUCCESS
) {
1007 if (ret_persistent_handle
)
1008 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
1012 if (rc
!= TPM2_RC_NV_DEFINED
)
1013 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1014 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc
));
1017 if (ret_persistent_handle
)
1018 *ret_persistent_handle
= NULL
;
1023 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
1025 static int tpm2_credit_random(Tpm2Context
*c
) {
1026 size_t rps
, done
= 0;
1033 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
1034 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
1035 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
1038 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH
, F_OK
) < 0) {
1039 if (errno
!= ENOENT
)
1040 log_debug_errno(errno
, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH
"' exists, ignoring: %m");
1042 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
1043 return 0; /* Already done */
1046 t
= now(CLOCK_MONOTONIC
);
1048 for (rps
= random_pool_size(); rps
> 0;) {
1049 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
1051 rc
= sym_Esys_GetRandom(
1056 MIN(rps
, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1058 if (rc
!= TSS2_RC_SUCCESS
)
1059 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1060 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc
));
1062 if (buffer
->size
== 0)
1063 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1064 "Zero-sized entropy returned from TPM.");
1066 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
1068 return log_debug_errno(r
, "Failed wo write entropy to kernel: %m");
1070 done
+= buffer
->size
;
1071 rps
= LESS_BY(rps
, buffer
->size
);
1074 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
1076 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
1078 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
1083 /* Get one of the legacy primary key templates.
1085 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1086 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1087 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1088 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1089 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1090 /* Do not modify. */
1091 static const TPMT_PUBLIC legacy_ecc
= {
1092 .type
= TPM2_ALG_ECC
,
1093 .nameAlg
= TPM2_ALG_SHA256
,
1095 TPMA_OBJECT_RESTRICTED
|
1096 TPMA_OBJECT_DECRYPT
|
1097 TPMA_OBJECT_FIXEDTPM
|
1098 TPMA_OBJECT_FIXEDPARENT
|
1099 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1100 TPMA_OBJECT_USERWITHAUTH
,
1101 .parameters
.eccDetail
= {
1103 .algorithm
= TPM2_ALG_AES
,
1105 .mode
.aes
= TPM2_ALG_CFB
,
1107 .scheme
.scheme
= TPM2_ALG_NULL
,
1108 .curveID
= TPM2_ECC_NIST_P256
,
1109 .kdf
.scheme
= TPM2_ALG_NULL
,
1113 /* Do not modify. */
1114 static const TPMT_PUBLIC legacy_rsa
= {
1115 .type
= TPM2_ALG_RSA
,
1116 .nameAlg
= TPM2_ALG_SHA256
,
1117 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
1118 .parameters
.rsaDetail
= {
1120 .algorithm
= TPM2_ALG_AES
,
1122 .mode
.aes
= TPM2_ALG_CFB
,
1124 .scheme
.scheme
= TPM2_ALG_NULL
,
1129 assert(ret_template
);
1131 if (alg
== TPM2_ALG_ECC
)
1132 *ret_template
= legacy_ecc
;
1133 else if (alg
== TPM2_ALG_RSA
)
1134 *ret_template
= legacy_rsa
;
1136 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1137 "Unsupported legacy SRK alg: 0x%x", alg
);
1142 /* Get a Storage Root Key (SRK) template.
1144 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1145 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1146 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1147 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1150 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1151 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1153 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1154 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1155 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1157 * Returns 0 if the specified algorithm is ECC or RSA, otherwise -EOPNOTSUPP. */
1158 int tpm2_get_srk_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1159 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1160 * Provisioning Guidance document, specifically:
1161 * TPMA_OBJECT_USERWITHAUTH is added.
1162 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1163 * TPMA_OBJECT_NODA is added. */
1164 TPMA_OBJECT srk_attributes
=
1165 TPMA_OBJECT_DECRYPT
|
1166 TPMA_OBJECT_FIXEDPARENT
|
1167 TPMA_OBJECT_FIXEDTPM
|
1169 TPMA_OBJECT_RESTRICTED
|
1170 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1171 TPMA_OBJECT_USERWITHAUTH
;
1173 /* The symmetric configuration is the same between ECC and RSA templates. */
1174 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1175 .algorithm
= TPM2_ALG_AES
,
1177 .mode
.aes
= TPM2_ALG_CFB
,
1180 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1182 /* From the EK Credential Profile template "L-2". */
1183 TPMT_PUBLIC srk_ecc
= {
1184 .type
= TPM2_ALG_ECC
,
1185 .nameAlg
= TPM2_ALG_SHA256
,
1186 .objectAttributes
= srk_attributes
,
1187 .parameters
.eccDetail
= {
1188 .symmetric
= srk_symmetric
,
1189 .scheme
.scheme
= TPM2_ALG_NULL
,
1190 .curveID
= TPM2_ECC_NIST_P256
,
1191 .kdf
.scheme
= TPM2_ALG_NULL
,
1195 /* From the EK Credential Profile template "L-1". */
1196 TPMT_PUBLIC srk_rsa
= {
1197 .type
= TPM2_ALG_RSA
,
1198 .nameAlg
= TPM2_ALG_SHA256
,
1199 .objectAttributes
= srk_attributes
,
1200 .parameters
.rsaDetail
= {
1201 .symmetric
= srk_symmetric
,
1202 .scheme
.scheme
= TPM2_ALG_NULL
,
1207 assert(ret_template
);
1211 *ret_template
= srk_ecc
;
1214 *ret_template
= srk_rsa
;
1218 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "No SRK for algorithm 0x%" PRIx16
, alg
);
1221 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1222 int tpm2_get_best_srk_template(Tpm2Context
*c
, TPMT_PUBLIC
*ret_template
) {
1223 TPMT_PUBLIC
template;
1227 assert(ret_template
);
1229 r
= tpm2_get_srk_template(TPM2_ALG_ECC
, &template);
1233 if (!tpm2_supports_alg(c
, TPM2_ALG_ECC
))
1234 log_debug("TPM does not support ECC.");
1235 else if (!tpm2_supports_ecc_curve(c
, template.parameters
.eccDetail
.curveID
))
1236 log_debug("TPM does not support ECC-NIST-P256 curve.");
1237 else if (!tpm2_supports_tpmt_public(c
, &template))
1238 log_debug("TPM does not support SRK ECC template L-2.");
1240 *ret_template
= template;
1244 r
= tpm2_get_srk_template(TPM2_ALG_RSA
, &template);
1248 if (!tpm2_supports_alg(c
, TPM2_ALG_RSA
))
1249 log_debug("TPM does not support RSA.");
1250 else if (!tpm2_supports_tpmt_public(c
, &template))
1251 log_debug("TPM does not support SRK RSA template L-1.");
1253 *ret_template
= template;
1257 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1258 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1261 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1262 * tpm2_get_or_create_srk() below. */
1265 const Tpm2Handle
*session
,
1266 TPM2B_PUBLIC
**ret_public
,
1267 TPM2B_NAME
**ret_name
,
1268 TPM2B_NAME
**ret_qname
,
1269 Tpm2Handle
**ret_handle
) {
1271 return tpm2_index_to_handle(c
, TPM2_SRK_HANDLE
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1274 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1275 * exists, or < 0 on error. */
1276 int tpm2_get_or_create_srk(
1278 const Tpm2Handle
*session
,
1279 TPM2B_PUBLIC
**ret_public
,
1280 TPM2B_NAME
**ret_name
,
1281 TPM2B_NAME
**ret_qname
,
1282 Tpm2Handle
**ret_handle
) {
1286 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1290 return 0; /* 0 → SRK already set up */
1292 /* No SRK, create and persist one */
1293 TPM2B_PUBLIC
template = {
1294 .size
= sizeof(TPMT_PUBLIC
),
1296 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1298 return log_debug_errno(r
, "Could not get best SRK template: %m");
1300 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1301 r
= tpm2_create_primary(
1305 /* sensitive= */ NULL
,
1306 /* ret_public= */ NULL
,
1311 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1312 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1313 * either case, all threads will get the persistent SRK below. */
1314 r
= tpm2_persist_handle(c
, transient_handle
, session
, TPM2_SRK_HANDLE
, /* ret_persistent_handle= */ NULL
);
1318 /* The SRK should exist now. */
1319 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1323 /* This should never happen. */
1324 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1326 return 1; /* > 0 → SRK newly set up */
1329 /* Utility functions for TPMS_PCR_SELECTION. */
1331 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1332 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1334 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1337 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1338 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
1342 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1343 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPMS_PCR_SELECTION
*ret
) {
1346 /* This is currently hardcoded at 24 PCRs, above. */
1347 if (!TPM2_PCR_MASK_VALID(mask
))
1348 log_debug("PCR mask selections (%x) out of range, ignoring.",
1349 mask
& ~((uint32_t)TPM2_PCRS_MASK
));
1351 *ret
= (TPMS_PCR_SELECTION
){
1353 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1354 .pcrSelect
[0] = mask
& 0xff,
1355 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1356 .pcrSelect
[2] = (mask
>> 16) & 0xff,
1360 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1361 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1364 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1367 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1370 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
1373 /* Add all PCR selections in the mask. */
1374 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1375 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 1);
1378 /* Remove all PCR selections in the mask. */
1379 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1380 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 0);
1383 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1384 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1387 assert(a
->hash
== b
->hash
);
1389 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1392 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1393 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1396 assert(a
->hash
== b
->hash
);
1398 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1401 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1402 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION
*a
, TPMS_PCR_SELECTION
*b
) {
1406 tpm2_tpms_pcr_selection_add(a
, b
);
1407 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
1410 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1411 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1412 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1413 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1414 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1416 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1417 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1419 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1420 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1421 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1423 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1426 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1428 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1432 return strjoin(algstr
, "(", mask
, ")");
1435 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1438 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1441 /* Utility functions for TPML_PCR_SELECTION. */
1443 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1444 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION
*l
, uint32_t index
) {
1446 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1447 assert(index
< l
->count
);
1449 size_t s
= l
->count
- (index
+ 1);
1450 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
1454 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1455 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1456 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1457 static TPMS_PCR_SELECTION
*tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1458 TPML_PCR_SELECTION
*l
,
1459 TPMI_ALG_HASH hash_alg
) {
1462 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1464 TPMS_PCR_SELECTION
*selection
= NULL
;
1465 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1466 if (s
->hash
== hash_alg
) {
1474 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1475 for (uint32_t i
= l
->count
- 1; i
> 0; i
--) {
1476 TPMS_PCR_SELECTION
*s
= &l
->pcrSelections
[i
];
1481 if (s
->hash
== hash_alg
) {
1482 tpm2_tpms_pcr_selection_move(selection
, s
);
1483 tpm2_tpml_pcr_selection_remove_index(l
, i
);
1490 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1491 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION
*l
) {
1492 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1493 for (uint32_t i
= 0; i
< l
->count
; i
++)
1494 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1495 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, l
->pcrSelections
[i
].hash
);
1498 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1499 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash_alg
) {
1502 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1503 * are multiple entries with the requested hash alg. */
1504 TPML_PCR_SELECTION lcopy
= *l
;
1506 TPMS_PCR_SELECTION
*s
;
1507 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1511 return tpm2_tpms_pcr_selection_to_mask(s
);
1514 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1515 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPML_PCR_SELECTION
*ret
) {
1518 TPMS_PCR_SELECTION s
;
1519 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1521 *ret
= (TPML_PCR_SELECTION
){
1523 .pcrSelections
[0] = s
,
1527 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1528 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1529 * entries with the same hash alg. */
1530 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1534 if (tpm2_tpms_pcr_selection_is_empty(s
))
1537 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1539 tpm2_tpms_pcr_selection_add(selection
, s
);
1543 /* It's already broken if the count is higher than the array has size for. */
1544 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1546 /* If full, the cleanup should result in at least one available entry. */
1547 if (l
->count
== ELEMENTSOF(l
->pcrSelections
))
1548 tpm2_tpml_pcr_selection_cleanup(l
);
1550 assert(l
->count
< ELEMENTSOF(l
->pcrSelections
));
1551 l
->pcrSelections
[l
->count
++] = *s
;
1554 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1555 * will combine all entries for 's->hash' in 'l'. */
1556 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1560 if (tpm2_tpms_pcr_selection_is_empty(s
))
1563 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1565 tpm2_tpms_pcr_selection_sub(selection
, s
);
1568 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1569 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1572 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l
, hash
), mask
);
1575 /* Add the PCR selections in the mask, with the provided hash. */
1576 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1577 TPMS_PCR_SELECTION tpms
;
1581 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1582 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l
, &tpms
);
1585 /* Remove the PCR selections in the mask, with the provided hash. */
1586 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1587 TPMS_PCR_SELECTION tpms
;
1591 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1592 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l
, &tpms
);
1595 /* Add all PCR selections in 'b' to 'a'. */
1596 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1600 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1601 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a
, selection_b
);
1604 /* Remove all PCR selections in 'b' from 'a'. */
1605 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1609 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1610 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a
, selection_b
);
1613 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION
*l
) {
1616 _cleanup_free_
char *banks
= NULL
;
1617 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1618 if (tpm2_tpms_pcr_selection_is_empty(s
))
1621 _cleanup_free_
char *str
= tpm2_tpms_pcr_selection_to_string(s
);
1622 if (!str
|| !strextend_with_separator(&banks
, ",", str
))
1626 return strjoin("[", strempty(banks
), "]");
1629 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION
*l
) {
1631 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1634 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1635 size_t w
= tpm2_tpms_pcr_selection_weight(s
);
1636 assert(weight
<= SIZE_MAX
- w
);
1643 bool tpm2_pcr_value_valid(const Tpm2PCRValue
*pcr_value
) {
1649 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1650 log_debug("PCR index %u invalid.", pcr_value
->index
);
1654 /* If it contains a value, the value size must match the hash size. */
1655 if (pcr_value
->value
.size
> 0) {
1656 r
= tpm2_hash_alg_to_size(pcr_value
->hash
);
1660 if (pcr_value
->value
.size
!= (size_t) r
) {
1661 log_debug("PCR hash 0x%" PRIx16
" expected size %d does not match actual size %" PRIu16
".",
1662 pcr_value
->hash
, r
, pcr_value
->value
.size
);
1670 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1672 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1673 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1675 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1677 bool tpm2_pcr_values_valid(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1678 if (!pcr_values
&& n_pcr_values
> 0)
1681 const Tpm2PCRValue
*previous
= NULL
;
1682 FOREACH_ARRAY(current
, pcr_values
, n_pcr_values
) {
1683 if (!tpm2_pcr_value_valid(current
))
1691 /* Hashes must be sorted in ascending order */
1692 if (current
->hash
< previous
->hash
) {
1693 log_debug("PCR values not in ascending order, hash %" PRIu16
" is after %" PRIu16
".",
1694 current
->hash
, previous
->hash
);
1698 if (current
->hash
== previous
->hash
) {
1699 /* Indexes (for the same hash) must be sorted in ascending order */
1700 if (current
->index
< previous
->index
) {
1701 log_debug("PCR values not in ascending order, hash %" PRIu16
" index %u is after %u.",
1702 current
->hash
, current
->index
, previous
->index
);
1706 /* Indexes (for the same hash) must not be duplicates */
1707 if (current
->index
== previous
->index
) {
1708 log_debug("PCR values contain duplicates for hash %" PRIu16
" index %u.",
1709 current
->hash
, previous
->index
);
1718 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1719 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1720 assert(pcr_values
|| n_pcr_values
== 0);
1722 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1723 if (v
->value
.size
> 0)
1729 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1730 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1731 assert(pcr_values
|| n_pcr_values
== 0);
1733 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1734 if (v
->value
.size
== 0)
1740 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1744 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
1747 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1748 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1749 void tpm2_sort_pcr_values(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1750 typesafe_qsort(pcr_values
, n_pcr_values
, cmp_pcr_values
);
1753 int tpm2_pcr_values_from_mask(uint32_t mask
, TPMI_ALG_HASH hash
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1754 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1755 size_t n_pcr_values
= 0;
1757 assert(ret_pcr_values
);
1758 assert(ret_n_pcr_values
);
1760 FOREACH_PCR_IN_MASK(index
, mask
)
1761 if (!GREEDY_REALLOC_APPEND(
1764 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1766 return log_oom_debug();
1768 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1769 *ret_n_pcr_values
= n_pcr_values
;
1774 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1777 assert(pcr_values
|| n_pcr_values
== 0);
1780 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1781 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1783 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1784 if (v
->hash
== hash
)
1785 SET_BIT(mask
, v
->index
);
1792 int tpm2_tpml_pcr_selection_from_pcr_values(
1793 const Tpm2PCRValue
*pcr_values
,
1794 size_t n_pcr_values
,
1795 TPML_PCR_SELECTION
*ret_selection
,
1796 TPM2B_DIGEST
**ret_values
,
1797 size_t *ret_n_values
) {
1799 TPML_PCR_SELECTION selection
= {};
1800 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1801 size_t n_values
= 0;
1803 assert(pcr_values
|| n_pcr_values
== 0);
1805 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1806 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR values are not valid.");
1808 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1809 tpm2_tpml_pcr_selection_add_mask(&selection
, v
->hash
, INDEX_TO_MASK(uint32_t, v
->index
));
1811 if (!GREEDY_REALLOC_APPEND(values
, n_values
, &v
->value
, 1))
1812 return log_oom_debug();
1816 *ret_selection
= selection
;
1818 *ret_values
= TAKE_PTR(values
);
1820 *ret_n_values
= n_values
;
1825 /* Count the number of different hash algorithms for all the entries. */
1826 int tpm2_pcr_values_hash_count(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, size_t *ret_count
) {
1827 TPML_PCR_SELECTION selection
;
1833 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1837 /* ret_values= */ NULL
,
1838 /* ret_n_values= */ NULL
);
1842 *ret_count
= selection
.count
;
1847 /* Parse a string argument into a Tpm2PCRValue object.
1849 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1850 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1851 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1852 int tpm2_pcr_value_from_string(const char *arg
, Tpm2PCRValue
*ret_pcr_value
) {
1853 Tpm2PCRValue pcr_value
= {};
1854 const char *p
= arg
;
1858 assert(ret_pcr_value
);
1860 _cleanup_free_
char *index
= NULL
;
1861 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1863 return log_debug_errno(r
, "Could not parse pcr value '%s': %m", p
);
1865 r
= tpm2_pcr_index_from_string(index
);
1867 return log_debug_errno(r
, "Invalid pcr index '%s': %m", index
);
1868 pcr_value
.index
= (unsigned) r
;
1871 _cleanup_free_
char *hash
= NULL
;
1872 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1874 return log_debug_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1876 r
= tpm2_hash_alg_from_string(hash
);
1878 return log_debug_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1879 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1882 /* Remove leading 0x if present */
1883 p
= startswith_no_case(p
, "0x") ?: p
;
1885 _cleanup_free_
void *buf
= NULL
;
1886 size_t buf_size
= 0;
1887 r
= unhexmem(p
, &buf
, &buf_size
);
1889 return log_debug_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1891 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1893 return log_debug_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1895 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1899 *ret_pcr_value
= pcr_value
;
1904 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1905 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1906 * string. This does not check for validity. */
1907 char *tpm2_pcr_value_to_string(const Tpm2PCRValue
*pcr_value
) {
1908 _cleanup_free_
char *index
= NULL
, *value
= NULL
;
1910 if (asprintf(&index
, "%u", pcr_value
->index
) < 0)
1913 const char *hash
= pcr_value
->hash
> 0 ? tpm2_hash_alg_to_string(pcr_value
->hash
) : NULL
;
1915 if (hash
&& pcr_value
->value
.size
> 0) {
1916 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1921 return strjoin(index
, hash
? ":" : "", strempty(hash
), value
? "=" : "", strempty(value
));
1924 /* Parse a string argument into an array of Tpm2PCRValue objects.
1926 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1927 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1928 int tpm2_pcr_values_from_string(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1929 const char *p
= arg
;
1933 assert(ret_pcr_values
);
1934 assert(ret_n_pcr_values
);
1936 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1937 size_t n_pcr_values
= 0;
1940 _cleanup_free_
char *pcr_arg
= NULL
;
1941 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1943 return log_debug_errno(r
, "Could not parse pcr values '%s': %m", p
);
1947 Tpm2PCRValue pcr_value
;
1948 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1952 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1953 return log_oom_debug();
1956 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1957 *ret_n_pcr_values
= n_pcr_values
;
1962 /* Return a string representing the array of PCR values. The format is as described in
1963 * tpm2_pcr_values_from_string(). This does not check for validity. */
1964 char *tpm2_pcr_values_to_string(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1965 _cleanup_free_
char *s
= NULL
;
1967 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1968 _cleanup_free_
char *pcrstr
= tpm2_pcr_value_to_string(v
);
1969 if (!pcrstr
|| !strextend_with_separator(&s
, "+", pcrstr
))
1973 return s
? TAKE_PTR(s
) : strdup("");
1976 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
1977 if (!DEBUG_LOGGING
|| !l
)
1980 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
1981 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
1984 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
1985 if (!DEBUG_LOGGING
|| !pcr_value
)
1988 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
1989 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
1992 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
1993 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
1996 _cleanup_free_
char *h
= hexmem(buffer
, size
);
1997 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
2000 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
2002 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
2005 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
2007 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
2010 static int tpm2_get_policy_digest(
2012 const Tpm2Handle
*session
,
2013 TPM2B_DIGEST
**ret_policy_digest
) {
2017 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
2023 log_debug("Acquiring policy digest.");
2025 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
2026 rc
= sym_Esys_PolicyGetDigest(
2028 session
->esys_handle
,
2033 if (rc
!= TSS2_RC_SUCCESS
)
2034 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2035 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc
));
2037 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
2039 if (ret_policy_digest
)
2040 *ret_policy_digest
= TAKE_PTR(policy_digest
);
2045 int tpm2_create_primary(
2047 const Tpm2Handle
*session
,
2048 const TPM2B_PUBLIC
*template,
2049 const TPM2B_SENSITIVE_CREATE
*sensitive
,
2050 TPM2B_PUBLIC
**ret_public
,
2051 Tpm2Handle
**ret_handle
) {
2060 log_debug("Creating primary key on TPM.");
2062 ts
= now(CLOCK_MONOTONIC
);
2064 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2065 r
= tpm2_handle_new(c
, &handle
);
2069 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2070 rc
= sym_Esys_CreatePrimary(
2073 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2076 sensitive
?: &(TPM2B_SENSITIVE_CREATE
) {},
2078 /* outsideInfo= */ NULL
,
2079 &(TPML_PCR_SELECTION
) {},
2080 &handle
->esys_handle
,
2082 /* creationData= */ NULL
,
2083 /* creationHash= */ NULL
,
2084 /* creationTicket= */ NULL
);
2085 if (rc
!= TSS2_RC_SUCCESS
)
2086 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2087 "Failed to generate primary key in TPM: %s",
2088 sym_Tss2_RC_Decode(rc
));
2090 log_debug("Successfully created primary key on TPM in %s.",
2091 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2094 *ret_public
= TAKE_PTR(public);
2096 *ret_handle
= TAKE_PTR(handle
);
2101 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2102 * instead use tpm2_create_primary(). */
2103 int tpm2_create(Tpm2Context
*c
,
2104 const Tpm2Handle
*parent
,
2105 const Tpm2Handle
*session
,
2106 const TPMT_PUBLIC
*template,
2107 const TPMS_SENSITIVE_CREATE
*sensitive
,
2108 TPM2B_PUBLIC
**ret_public
,
2109 TPM2B_PRIVATE
**ret_private
) {
2118 log_debug("Creating object on TPM.");
2120 ts
= now(CLOCK_MONOTONIC
);
2122 TPM2B_PUBLIC tpm2b_public
= {
2123 .size
= sizeof(*template) - sizeof(template->unique
),
2124 .publicArea
= *template,
2127 /* Zero the unique area. */
2128 zero(tpm2b_public
.publicArea
.unique
);
2130 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2132 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2133 .size
= sizeof(*sensitive
),
2134 .sensitive
= *sensitive
,
2137 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2139 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2140 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2141 rc
= sym_Esys_Create(
2143 parent
->esys_handle
,
2144 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2149 /* outsideInfo= */ NULL
,
2150 &(TPML_PCR_SELECTION
) {},
2153 /* creationData= */ NULL
,
2154 /* creationHash= */ NULL
,
2155 /* creationTicket= */ NULL
);
2156 if (rc
!= TSS2_RC_SUCCESS
)
2157 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2158 "Failed to generate object in TPM: %s",
2159 sym_Tss2_RC_Decode(rc
));
2161 log_debug("Successfully created object on TPM in %s.",
2162 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2165 *ret_public
= TAKE_PTR(public);
2167 *ret_private
= TAKE_PTR(private);
2174 const Tpm2Handle
*parent
,
2175 const Tpm2Handle
*session
,
2176 const TPM2B_PUBLIC
*public,
2177 const TPM2B_PRIVATE
*private,
2178 Tpm2Handle
**ret_handle
) {
2188 log_debug("Loading object into TPM.");
2190 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2191 r
= tpm2_handle_new(c
, &handle
);
2197 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2198 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2203 &handle
->esys_handle
);
2204 if (rc
== TPM2_RC_LOCKOUT
)
2205 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK
),
2206 "TPM2 device is in dictionary attack lockout mode.");
2207 if (rc
!= TSS2_RC_SUCCESS
)
2208 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2209 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2211 *ret_handle
= TAKE_PTR(handle
);
2216 static int tpm2_load_external(
2218 const Tpm2Handle
*session
,
2219 const TPM2B_PUBLIC
*public,
2220 const TPM2B_SENSITIVE
*private,
2221 Tpm2Handle
**ret_handle
) {
2229 log_debug("Loading external key into TPM.");
2231 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2232 r
= tpm2_handle_new(c
, &handle
);
2236 rc
= sym_Esys_LoadExternal(
2238 session
? session
->esys_handle
: ESYS_TR_NONE
,
2244 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2245 * hierarchy, older versions need TPM2_RH_* instead. */
2246 private ? ESYS_TR_RH_NULL
: ESYS_TR_RH_OWNER
,
2248 private ? TPM2_RH_NULL
: TPM2_RH_OWNER
,
2250 &handle
->esys_handle
);
2251 if (rc
!= TSS2_RC_SUCCESS
)
2252 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2253 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2255 *ret_handle
= TAKE_PTR(handle
);
2260 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2261 * use tpm2_create_loaded(). */
2262 static int _tpm2_create_loaded(
2264 const Tpm2Handle
*parent
,
2265 const Tpm2Handle
*session
,
2266 const TPMT_PUBLIC
*template,
2267 const TPMS_SENSITIVE_CREATE
*sensitive
,
2268 TPM2B_PUBLIC
**ret_public
,
2269 TPM2B_PRIVATE
**ret_private
,
2270 Tpm2Handle
**ret_handle
) {
2280 log_debug("Creating loaded object on TPM.");
2282 ts
= now(CLOCK_MONOTONIC
);
2284 /* Copy the input template and zero the unique area. */
2285 TPMT_PUBLIC template_copy
= *template;
2286 zero(template_copy
.unique
);
2288 TPM2B_TEMPLATE tpm2b_template
;
2290 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2292 tpm2b_template
.buffer
,
2293 sizeof(tpm2b_template
.buffer
),
2295 if (rc
!= TSS2_RC_SUCCESS
)
2296 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2297 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc
));
2298 assert(size
<= UINT16_MAX
);
2299 tpm2b_template
.size
= size
;
2301 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2303 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2304 .size
= sizeof(*sensitive
),
2305 .sensitive
= *sensitive
,
2308 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2310 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2311 r
= tpm2_handle_new(c
, &handle
);
2315 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2316 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2317 rc
= sym_Esys_CreateLoaded(
2319 parent
->esys_handle
,
2320 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2325 &handle
->esys_handle
,
2328 if (rc
!= TSS2_RC_SUCCESS
)
2329 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2330 "Failed to generate loaded object in TPM: %s",
2331 sym_Tss2_RC_Decode(rc
));
2333 log_debug("Successfully created loaded object on TPM in %s.",
2334 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2337 *ret_public
= TAKE_PTR(public);
2339 *ret_private
= TAKE_PTR(private);
2341 *ret_handle
= TAKE_PTR(handle
);
2346 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2347 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2348 * tpm2_create_primary(). */
2349 int tpm2_create_loaded(
2351 const Tpm2Handle
*parent
,
2352 const Tpm2Handle
*session
,
2353 const TPMT_PUBLIC
*template,
2354 const TPMS_SENSITIVE_CREATE
*sensitive
,
2355 TPM2B_PUBLIC
**ret_public
,
2356 TPM2B_PRIVATE
**ret_private
,
2357 Tpm2Handle
**ret_handle
) {
2361 if (tpm2_supports_command(c
, TPM2_CC_CreateLoaded
))
2362 return _tpm2_create_loaded(c
, parent
, session
, template, sensitive
, ret_public
, ret_private
, ret_handle
);
2364 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2365 * create and load manually. */
2366 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2367 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2368 r
= tpm2_create(c
, parent
, session
, template, sensitive
, &public, &private);
2372 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2373 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2378 *ret_public
= TAKE_PTR(public);
2380 *ret_private
= TAKE_PTR(private);
2382 *ret_handle
= TAKE_PTR(handle
);
2387 static int tpm2_marshal_private(const TPM2B_PRIVATE
*private, void **ret
, size_t *ret_size
) {
2388 size_t max_size
= sizeof(*private), blob_size
= 0;
2389 _cleanup_free_
void *blob
= NULL
;
2396 blob
= malloc0(max_size
);
2398 return log_oom_debug();
2400 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
2401 if (rc
!= TSS2_RC_SUCCESS
)
2402 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2403 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
2405 *ret
= TAKE_PTR(blob
);
2406 *ret_size
= blob_size
;
2410 static int tpm2_unmarshal_private(const void *data
, size_t size
, TPM2B_PRIVATE
*ret_private
) {
2411 TPM2B_PRIVATE
private = {};
2415 assert(data
|| size
== 0);
2416 assert(ret_private
);
2418 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(data
, size
, &offset
, &private);
2419 if (rc
!= TSS2_RC_SUCCESS
)
2420 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2421 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
2423 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2424 "Garbage at end of private key marshal data.");
2426 *ret_private
= private;
2430 int tpm2_marshal_public(const TPM2B_PUBLIC
*public, void **ret
, size_t *ret_size
) {
2431 size_t max_size
= sizeof(*public), blob_size
= 0;
2432 _cleanup_free_
void *blob
= NULL
;
2439 blob
= malloc0(max_size
);
2441 return log_oom_debug();
2443 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
2444 if (rc
!= TSS2_RC_SUCCESS
)
2445 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2446 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
2448 *ret
= TAKE_PTR(blob
);
2449 *ret_size
= blob_size
;
2453 static int tpm2_unmarshal_public(const void *data
, size_t size
, TPM2B_PUBLIC
*ret_public
) {
2454 TPM2B_PUBLIC
public = {};
2458 assert(data
|| size
== 0);
2461 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(data
, size
, &offset
, &public);
2462 if (rc
!= TSS2_RC_SUCCESS
)
2463 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2464 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
2466 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2467 "Garbage at end of public key marshal data.");
2469 *ret_public
= public;
2473 int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC
*nv_public
, void **ret
, size_t *ret_size
) {
2474 size_t max_size
= sizeof(*nv_public
), blob_size
= 0;
2475 _cleanup_free_
void *blob
= NULL
;
2482 blob
= malloc0(max_size
);
2484 return log_oom_debug();
2486 rc
= sym_Tss2_MU_TPM2B_NV_PUBLIC_Marshal(nv_public
, blob
, max_size
, &blob_size
);
2487 if (rc
!= TSS2_RC_SUCCESS
)
2488 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2489 "Failed to marshal NV public structure: %s", sym_Tss2_RC_Decode(rc
));
2491 *ret
= TAKE_PTR(blob
);
2492 *ret_size
= blob_size
;
2496 int tpm2_unmarshal_nv_public(const void *data
, size_t size
, TPM2B_NV_PUBLIC
*ret_nv_public
) {
2497 TPM2B_NV_PUBLIC nv_public
= {};
2501 assert(data
|| size
== 0);
2502 assert(ret_nv_public
);
2504 rc
= sym_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal(data
, size
, &offset
, &nv_public
);
2505 if (rc
!= TSS2_RC_SUCCESS
)
2506 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2507 "Failed to unmarshal NV public structure: %s", sym_Tss2_RC_Decode(rc
));
2509 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2510 "Garbage at end of NV public structure marshal data.");
2512 *ret_nv_public
= nv_public
;
2516 static int tpm2_import(
2518 const Tpm2Handle
*parent
,
2519 const Tpm2Handle
*session
,
2520 const TPM2B_PUBLIC
*public,
2521 const TPM2B_PRIVATE
*private,
2522 const TPM2B_ENCRYPTED_SECRET
*seed
,
2523 const TPM2B_DATA
*encryption_key
,
2524 const TPMT_SYM_DEF_OBJECT
*symmetric
,
2525 TPM2B_PRIVATE
**ret_private
) {
2531 assert(!!encryption_key
== !!symmetric
);
2535 assert(ret_private
);
2537 log_debug("Importing key into TPM.");
2539 rc
= sym_Esys_Import(
2541 parent
->esys_handle
,
2542 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2549 symmetric
?: &(TPMT_SYM_DEF_OBJECT
){ .algorithm
= TPM2_ALG_NULL
, },
2551 if (rc
!= TSS2_RC_SUCCESS
)
2552 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2553 "Failed to import key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2558 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2559 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2560 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2561 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2565 const TPML_PCR_SELECTION
*pcr_selection
,
2566 Tpm2PCRValue
**ret_pcr_values
,
2567 size_t *ret_n_pcr_values
) {
2569 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2570 size_t n_pcr_values
= 0;
2574 assert(pcr_selection
);
2575 assert(ret_pcr_values
);
2576 assert(ret_n_pcr_values
);
2578 TPML_PCR_SELECTION remaining
= *pcr_selection
;
2579 while (!tpm2_tpml_pcr_selection_is_empty(&remaining
)) {
2580 _cleanup_(Esys_Freep
) TPML_PCR_SELECTION
*current_read
= NULL
;
2581 _cleanup_(Esys_Freep
) TPML_DIGEST
*current_values
= NULL
;
2583 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2585 /* Unfortunately, PCR_Read will not return more than 8 values. */
2586 rc
= sym_Esys_PCR_Read(
2595 if (rc
!= TSS2_RC_SUCCESS
)
2596 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2597 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc
));
2599 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2601 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2602 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2607 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2608 assert(i
< current_values
->count
);
2609 Tpm2PCRValue pcr_value
= {
2612 .value
= current_values
->digests
[i
++],
2615 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2617 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2618 return log_oom_debug();
2620 assert(i
== current_values
->count
);
2622 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2625 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
2627 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
2628 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "PCR values read from TPM are not valid.");
2630 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2631 *ret_n_pcr_values
= n_pcr_values
;
2636 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2637 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2638 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2639 * appropriate entries, this returns an error. This does not check the array for validity. */
2640 int tpm2_pcr_read_missing_values(Tpm2Context
*c
, Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2641 TPMI_ALG_HASH pcr_bank
= 0;
2645 assert(pcr_values
|| n_pcr_values
== 0);
2647 if (n_pcr_values
> 0) {
2649 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2651 return log_debug_errno(r
, "Could not get hash count from pcr values: %m");
2653 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2655 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2659 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2665 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2669 if (v
->value
.size
> 0)
2672 TPML_PCR_SELECTION selection
;
2673 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
2677 _cleanup_free_ Tpm2PCRValue
*read_values
= NULL
;
2678 size_t n_read_values
;
2679 r
= tpm2_pcr_read(c
, &selection
, &read_values
, &n_read_values
);
2683 if (n_read_values
== 0)
2684 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2685 "Could not read PCR hash 0x%" PRIu16
" index %u",
2688 assert(n_read_values
== 1);
2689 assert(read_values
[0].hash
== v
->hash
);
2690 assert(read_values
[0].index
== v
->index
);
2692 v
->value
= read_values
[0].value
;
2698 static int tpm2_pcr_mask_good(
2703 TPML_PCR_SELECTION selection
;
2708 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2709 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2710 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2712 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
2714 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2715 size_t n_pcr_values
;
2716 r
= tpm2_pcr_read(c
, &selection
, &pcr_values
, &n_pcr_values
);
2720 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2721 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
2722 if (!memeqbyte(0x00, v
->value
.buffer
, v
->value
.size
) &&
2723 !memeqbyte(0xFF, v
->value
.buffer
, v
->value
.size
))
2729 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
2733 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2734 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2735 if (selection
->sizeofSelect
< TPM2_PCRS_MAX
/8) {
2736 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2737 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2741 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
2743 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2744 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2746 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2747 if (selection
->pcrSelect
[j
] != 0xFF) {
2753 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2754 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2759 int tpm2_get_best_pcr_bank(
2762 TPMI_ALG_HASH
*ret
) {
2764 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
2770 if (pcr_mask
== 0) {
2771 log_debug("Asked to pick best PCR bank but no PCRs selected we could derive this from. Defaulting to SHA256.");
2772 *ret
= TPM2_ALG_SHA256
; /* if no PCRs are selected this doesn't matter anyway... */
2776 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2777 TPMI_ALG_HASH hash
= selection
->hash
;
2780 /* For now we are only interested in the SHA1 and SHA256 banks */
2781 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2784 r
= tpm2_bank_has24(selection
);
2790 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2794 if (hash
== TPM2_ALG_SHA256
) {
2795 supported_hash
= TPM2_ALG_SHA256
;
2797 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2798 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2802 assert(hash
== TPM2_ALG_SHA1
);
2804 if (supported_hash
== 0)
2805 supported_hash
= TPM2_ALG_SHA1
;
2807 if (good
&& hash_with_valid_pcr
== 0)
2808 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
2812 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2813 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2816 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2817 * not initialized. */
2819 if (hash_with_valid_pcr
== TPM2_ALG_SHA256
) {
2820 assert(supported_hash
== TPM2_ALG_SHA256
);
2821 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2822 *ret
= TPM2_ALG_SHA256
;
2823 } else if (hash_with_valid_pcr
== TPM2_ALG_SHA1
) {
2824 if (supported_hash
== TPM2_ALG_SHA256
)
2825 log_notice("TPM2 device supports both SHA1 and SHA256 PCR banks, but only SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
2827 assert(supported_hash
== TPM2_ALG_SHA1
);
2828 log_notice("TPM2 device lacks support for SHA256 PCR bank, but SHA1 bank is supported and SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
2831 *ret
= TPM2_ALG_SHA1
;
2832 } else if (supported_hash
== TPM2_ALG_SHA256
) {
2833 log_notice("TPM2 device supports SHA256 PCR bank but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA256 bank. PCR policy effectively unenforced!");
2834 *ret
= TPM2_ALG_SHA256
;
2835 } else if (supported_hash
== TPM2_ALG_SHA1
) {
2836 log_notice("TPM2 device lacks support for SHA256 bank, but SHA1 bank is supported, but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA1 bank. PCR policy effectively unenforced!");
2837 *ret
= TPM2_ALG_SHA1
;
2839 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2840 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2845 int tpm2_get_good_pcr_banks(
2848 TPMI_ALG_HASH
**ret
) {
2850 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2851 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2857 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2858 TPMI_ALG_HASH hash
= selection
->hash
;
2860 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2861 r
= tpm2_bank_has24(selection
);
2867 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2868 r
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2872 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2873 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2876 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2877 return log_oom_debug();
2879 good_banks
[n_good_banks
++] = hash
;
2881 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2882 return log_oom_debug();
2884 fallback_banks
[n_fallback_banks
++] = hash
;
2888 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2889 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2890 if (n_good_banks
> 0) {
2891 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks
);
2892 *ret
= TAKE_PTR(good_banks
);
2893 return (int) n_good_banks
;
2895 if (n_fallback_banks
> 0) {
2896 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks
);
2897 *ret
= TAKE_PTR(fallback_banks
);
2898 return (int) n_fallback_banks
;
2901 /* No suitable banks found. */
2906 int tpm2_get_good_pcr_banks_strv(
2912 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2913 _cleanup_strv_free_
char **l
= NULL
;
2919 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2923 FOREACH_ARRAY(a
, algs
, n_algs
) {
2924 _cleanup_free_
char *n
= NULL
;
2925 const EVP_MD
*implementation
;
2928 salg
= tpm2_hash_alg_to_string(*a
);
2930 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
2932 implementation
= EVP_get_digestbyname(salg
);
2933 if (!implementation
)
2934 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2936 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2938 return log_oom_debug();
2940 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2942 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2943 return log_oom_debug();
2948 #else /* HAVE_OPENSSL */
2949 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2953 /* Hash data into the digest.
2955 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2956 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2957 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2958 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2960 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2961 * correct for 'alg'.
2963 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2964 int tpm2_digest_many(
2966 TPM2B_DIGEST
*digest
,
2967 const struct iovec data
[],
2971 struct sha256_ctx ctx
;
2974 assert(data
|| n_data
== 0);
2976 if (alg
!= TPM2_ALG_SHA256
)
2977 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2978 "Hash algorithm not supported: 0x%x", alg
);
2980 if (extend
&& digest
->size
!= SHA256_DIGEST_SIZE
)
2981 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2982 "Digest size 0x%x, require 0x%x",
2983 digest
->size
, (unsigned)SHA256_DIGEST_SIZE
);
2985 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2986 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
2990 sha256_init_ctx(&ctx
);
2993 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
2995 *digest
= (TPM2B_DIGEST
) {
2996 .size
= SHA256_DIGEST_SIZE
,
2998 if (n_data
== 0) /* If not extending and no data, return zero hash */
3002 FOREACH_ARRAY(d
, data
, n_data
)
3003 sha256_process_bytes(d
->iov_base
, d
->iov_len
, &ctx
);
3005 sha256_finish_ctx(&ctx
, digest
->buffer
);
3010 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
3011 int tpm2_digest_many_digests(
3013 TPM2B_DIGEST
*digest
,
3014 const TPM2B_DIGEST data
[],
3018 _cleanup_free_
struct iovec
*iovecs
= NULL
;
3020 assert(data
|| n_data
== 0);
3022 iovecs
= new(struct iovec
, n_data
);
3024 return log_oom_debug();
3026 for (size_t i
= 0; i
< n_data
; i
++)
3027 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
3029 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
3032 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
3033 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
3034 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
3035 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
3036 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
3038 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
3039 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
3040 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
3041 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
3043 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
3044 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
3045 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
3047 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
3048 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
3049 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
3050 * which we will trim the 0(s) from before sending to the TPM.
3052 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
3053 bool trimmed
= false;
3057 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
3063 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
3066 int tpm2_auth_value_from_pin(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
3067 TPM2B_AUTH auth
= {};
3073 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
3077 tpm2_trim_auth_value(&auth
);
3079 *ret_auth
= TAKE_STRUCT(auth
);
3084 int tpm2_set_auth_binary(Tpm2Context
*c
, const Tpm2Handle
*handle
, const TPM2B_AUTH
*auth
) {
3093 rc
= sym_Esys_TR_SetAuth(c
->esys_context
, handle
->esys_handle
, auth
);
3094 if (rc
!= TSS2_RC_SUCCESS
)
3095 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3096 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc
));
3101 int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
3102 TPM2B_AUTH auth
= {};
3111 CLEANUP_ERASE(auth
);
3113 r
= tpm2_auth_value_from_pin(TPM2_ALG_SHA256
, pin
, &auth
);
3117 return tpm2_set_auth_binary(c
, handle
, &auth
);
3120 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
3121 TPMA_SESSION flags
= 0;
3127 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
3128 if (rc
!= TSS2_RC_SUCCESS
)
3131 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
3134 int tpm2_make_encryption_session(
3136 const Tpm2Handle
*primary
,
3137 const Tpm2Handle
*bind_key
,
3138 Tpm2Handle
**ret_session
) {
3140 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
3141 TPMA_SESSION_CONTINUESESSION
;
3147 assert(ret_session
);
3149 log_debug("Starting HMAC encryption session.");
3151 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
3152 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
3153 * recover the salt, which is then used for key derivation. */
3154 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
3155 r
= tpm2_handle_new(c
, &session
);
3159 rc
= sym_Esys_StartAuthSession(
3161 primary
->esys_handle
,
3162 bind_key
? bind_key
->esys_handle
: ESYS_TR_NONE
,
3168 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
3170 &session
->esys_handle
);
3171 if (rc
!= TSS2_RC_SUCCESS
)
3172 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3173 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
3175 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
3176 * always used for sessions), this provides confidentiality, integrity and replay protection for
3177 * operations that use this session. */
3178 rc
= sym_Esys_TRSess_SetAttributes(c
->esys_context
, session
->esys_handle
, sessionAttributes
, 0xff);
3179 if (rc
!= TSS2_RC_SUCCESS
)
3180 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3181 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc
));
3183 *ret_session
= TAKE_PTR(session
);
3188 int tpm2_make_policy_session(
3190 const Tpm2Handle
*primary
,
3191 const Tpm2Handle
*encryption_session
,
3192 Tpm2Handle
**ret_session
) {
3199 assert(encryption_session
);
3200 assert(ret_session
);
3202 if (!tpm2_is_encryption_session(c
, encryption_session
))
3203 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
3204 "Missing encryption session");
3206 log_debug("Starting policy session.");
3208 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
3209 r
= tpm2_handle_new(c
, &session
);
3213 rc
= sym_Esys_StartAuthSession(
3215 primary
->esys_handle
,
3217 encryption_session
->esys_handle
,
3222 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
3224 &session
->esys_handle
);
3225 if (rc
!= TSS2_RC_SUCCESS
)
3226 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3227 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
3229 *ret_session
= TAKE_PTR(session
);
3234 static int find_signature(
3236 const TPML_PCR_SELECTION
*pcr_selection
,
3241 void *ret_signature
,
3242 size_t *ret_signature_size
) {
3249 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3250 * public key, and policy digest. */
3252 if (!json_variant_is_object(v
))
3253 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
3255 uint16_t pcr_bank
= pcr_selection
->pcrSelections
[0].hash
;
3256 uint32_t pcr_mask
= tpm2_tpml_pcr_selection_to_mask(pcr_selection
, pcr_bank
);
3258 k
= tpm2_hash_alg_to_string(pcr_bank
);
3260 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
3262 /* First, find field by bank */
3263 b
= json_variant_by_key(v
, k
);
3265 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
3267 if (!json_variant_is_array(b
))
3268 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
3270 /* Now iterate through all signatures known for this bank */
3271 JSON_VARIANT_ARRAY_FOREACH(i
, b
) {
3272 _cleanup_free_
void *fpj_data
= NULL
, *polj_data
= NULL
;
3273 JsonVariant
*maskj
, *fpj
, *sigj
, *polj
;
3274 size_t fpj_size
, polj_size
;
3275 uint32_t parsed_mask
;
3277 if (!json_variant_is_object(i
))
3278 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
3280 /* Check if the PCR mask matches our expectations */
3281 maskj
= json_variant_by_key(i
, "pcrs");
3285 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
3287 return log_debug_errno(r
, "Failed to parse JSON PCR mask");
3289 if (parsed_mask
!= pcr_mask
)
3290 continue; /* Not for this PCR mask */
3292 /* Then check if this is for the public key we operate with */
3293 fpj
= json_variant_by_key(i
, "pkfp");
3297 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
3299 return log_debug_errno(r
, "Failed to decode fingerprint in JSON data: %m");
3301 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
3302 continue; /* Not for this public key */
3304 /* Finally, check if this is for the PCR policy we expect this to be */
3305 polj
= json_variant_by_key(i
, "pol");
3309 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
3311 return log_debug_errno(r
, "Failed to decode policy hash JSON data: %m");
3313 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
3316 /* This entry matches all our expectations, now return the signature included in it */
3317 sigj
= json_variant_by_key(i
, "sig");
3321 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
3324 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Couldn't find signature for this PCR bank, PCR index and public key.");
3325 #else /* HAVE_OPENSSL */
3326 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3330 /* Calculates the "name" of a public key.
3332 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3333 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3334 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3335 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3336 * that would also change the key name.
3338 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3339 * nameAlg is not TPM2_ALG_SHA256. */
3340 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC
*public, TPM2B_NAME
*ret_name
) {
3349 return log_debug_errno(r
, "TPM2 support not installed: %m");
3351 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3352 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3353 "Unsupported nameAlg: 0x%x",
3356 _cleanup_free_
uint8_t *buf
= NULL
;
3359 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3361 return log_oom_debug();
3363 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf
, sizeof(TPMT_PUBLIC
), &size
);
3364 if (rc
!= TSS2_RC_SUCCESS
)
3365 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3366 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3368 TPM2B_DIGEST digest
= {};
3369 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3374 .hashAlg
= TPM2_ALG_SHA256
,
3376 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3377 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3381 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3382 if (rc
!= TSS2_RC_SUCCESS
)
3383 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3384 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc
));
3387 tpm2_log_debug_name(&name
, "Calculated public key name");
3394 /* Get the "name" of a key from the TPM.
3396 * The "name" of a key is explained above in tpm2_calculate_pubkey_name().
3398 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3399 * public/private keypair. */
3402 const Tpm2Handle
*handle
,
3403 TPM2B_NAME
**ret_name
) {
3405 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
3412 rc
= sym_Esys_TR_GetName(c
->esys_context
, handle
->esys_handle
, &name
);
3413 if (rc
!= TSS2_RC_SUCCESS
)
3414 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3415 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc
));
3417 tpm2_log_debug_name(name
, "Object name");
3419 *ret_name
= TAKE_PTR(name
);
3424 int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC
*nvpublic
, TPM2B_NAME
*ret_name
) {
3433 return log_debug_errno(r
, "TPM2 support not installed: %m");
3435 if (nvpublic
->nameAlg
!= TPM2_ALG_SHA256
)
3436 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3437 "Unsupported nameAlg: 0x%x",
3440 _cleanup_free_
uint8_t *buf
= NULL
;
3443 buf
= (uint8_t*) new(TPMS_NV_PUBLIC
, 1);
3445 return log_oom_debug();
3447 rc
= sym_Tss2_MU_TPMS_NV_PUBLIC_Marshal(nvpublic
, buf
, sizeof(TPMS_NV_PUBLIC
), &size
);
3448 if (rc
!= TSS2_RC_SUCCESS
)
3449 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3450 "Failed to marshal NV index: %s", sym_Tss2_RC_Decode(rc
));
3452 TPM2B_DIGEST digest
= {};
3453 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3458 .hashAlg
= TPM2_ALG_SHA256
,
3460 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3461 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3465 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3466 if (rc
!= TSS2_RC_SUCCESS
)
3467 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3468 "Failed to marshal NV index name: %s", sym_Tss2_RC_Decode(rc
));
3471 tpm2_log_debug_name(&name
, "Calculated NV index name");
3478 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3479 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST
*digest
) {
3480 TPM2_CC command
= TPM2_CC_PolicyAuthValue
;
3485 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3489 return log_debug_errno(r
, "TPM2 support not installed: %m");
3491 uint8_t buf
[sizeof(command
)];
3494 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3495 if (rc
!= TSS2_RC_SUCCESS
)
3496 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3497 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc
));
3499 if (offset
!= sizeof(command
))
3500 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3501 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3503 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3507 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3512 int tpm2_policy_auth_value(
3514 const Tpm2Handle
*session
,
3515 TPM2B_DIGEST
**ret_policy_digest
) {
3522 log_debug("Submitting AuthValue policy.");
3524 rc
= sym_Esys_PolicyAuthValue(
3526 session
->esys_handle
,
3530 if (rc
!= TSS2_RC_SUCCESS
)
3531 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3532 "Failed to add authValue policy to TPM: %s",
3533 sym_Tss2_RC_Decode(rc
));
3535 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3538 /* Extend 'digest' with the PolicySigned calculated hash. */
3539 int tpm2_calculate_policy_signed(TPM2B_DIGEST
*digest
, const TPM2B_NAME
*name
) {
3540 TPM2_CC command
= TPM2_CC_PolicySigned
;
3545 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3550 return log_debug_errno(r
, "TPM2 support not installed: %m");
3552 uint8_t buf
[sizeof(command
)];
3555 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3556 if (rc
!= TSS2_RC_SUCCESS
)
3557 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3558 "Failed to marshal PolicySigned command: %s", sym_Tss2_RC_Decode(rc
));
3560 if (offset
!= sizeof(command
))
3561 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3562 "Offset 0x%zx wrong after marshalling PolicySigned command", offset
);
3564 struct iovec data
[] = {
3565 IOVEC_MAKE(buf
, offset
),
3566 IOVEC_MAKE(name
->name
, name
->size
),
3569 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3573 const TPM2B_NONCE policyRef
= {}; /* For now, we do not make use of the policyRef stuff */
3575 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, policyRef
.buffer
, policyRef
.size
, /* extend= */ true);
3579 tpm2_log_debug_digest(digest
, "PolicySigned calculated digest");
3584 int tpm2_policy_signed_hmac_sha256(
3586 const Tpm2Handle
*session
,
3587 const Tpm2Handle
*hmac_key_handle
,
3588 const struct iovec
*hmac_key
,
3589 TPM2B_DIGEST
**ret_policy_digest
) {
3597 assert(hmac_key_handle
);
3598 assert(iovec_is_set(hmac_key
));
3600 /* This sends a TPM2_PolicySigned command to the tpm. As signature key we use an HMAC-SHA256 key
3601 * specified in the hmac_key parameter. The secret key must be loaded into the TPM already and
3602 * referenced in hmac_key_handle. */
3604 log_debug("Submitting PolicySigned policy for HMAC-SHA256.");
3606 /* Acquire the nonce from the TPM that we shall sign */
3607 _cleanup_(Esys_Freep
) TPM2B_NONCE
*nonce
= NULL
;
3608 rc
= sym_Esys_TRSess_GetNonceTPM(
3610 session
->esys_handle
,
3612 if (rc
!= TSS2_RC_SUCCESS
)
3613 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3614 "Failed to determine NoneTPM of auth session: %s",
3615 sym_Tss2_RC_Decode(rc
));
3617 be32_t expiration
= htobe64(0);
3618 const TPM2B_DIGEST cpHashA
= {}; /* For now, we do not make use of the cpHashA stuff */
3619 const TPM2B_NONCE policyRef
= {}; /* ditto, we do not bother with policyRef */
3621 /* Put together the data to sign, as per TPM2 Spec Part 3, 23.3.1 */
3622 struct iovec data_to_sign
[] = {
3623 IOVEC_MAKE(nonce
->buffer
, nonce
->size
),
3624 IOVEC_MAKE(&expiration
, sizeof(expiration
)),
3625 IOVEC_MAKE(cpHashA
.buffer
, cpHashA
.size
),
3626 IOVEC_MAKE(policyRef
.buffer
, policyRef
.size
),
3629 /* Now calculate the digest of the data we put together */
3630 TPM2B_DIGEST digest_to_sign
;
3631 r
= tpm2_digest_many(TPM2_ALG_SHA256
, &digest_to_sign
, data_to_sign
, ELEMENTSOF(data_to_sign
), /* extend= */ false);
3635 unsigned char hmac_signature
[SHA256_DIGEST_SIZE
];
3636 unsigned hmac_signature_size
= sizeof(hmac_signature
);
3638 /* And sign this with our key */
3639 if (!HMAC(EVP_sha256(),
3642 digest_to_sign
.buffer
,
3643 digest_to_sign
.size
,
3645 &hmac_signature_size
))
3646 return -ENOTRECOVERABLE
;
3648 /* Now bring the signature into a format that the TPM understands */
3649 TPMT_SIGNATURE sig
= {
3650 .sigAlg
= TPM2_ALG_HMAC
,
3651 .signature
.hmac
.hashAlg
= TPM2_ALG_SHA256
,
3653 assert(hmac_signature_size
== sizeof(sig
.signature
.hmac
.digest
.sha256
));
3654 memcpy(sig
.signature
.hmac
.digest
.sha256
, hmac_signature
, hmac_signature_size
);
3656 /* And submit the whole shebang to the TPM */
3657 rc
= sym_Esys_PolicySigned(
3659 hmac_key_handle
->esys_handle
,
3660 session
->esys_handle
,
3661 /* shandle1= */ ESYS_TR_NONE
,
3662 /* shandle2= */ ESYS_TR_NONE
,
3663 /* shandle3= */ ESYS_TR_NONE
,
3669 /* timeout= */ NULL
,
3670 /* policyTicket= */ NULL
);
3671 if (rc
!= TSS2_RC_SUCCESS
)
3672 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3673 "Failed to add PolicySigned policy to TPM: %s",
3674 sym_Tss2_RC_Decode(rc
));
3676 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3677 #else /* HAVE_OPENSSL */
3678 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3682 int tpm2_calculate_policy_authorize_nv(
3683 const TPM2B_NV_PUBLIC
*public_info
,
3684 TPM2B_DIGEST
*digest
) {
3685 TPM2_CC command
= TPM2_CC_PolicyAuthorizeNV
;
3689 assert(public_info
);
3691 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3695 return log_debug_errno(r
, "TPM2 support not installed: %m");
3697 uint8_t buf
[sizeof(command
)];
3700 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3701 if (rc
!= TSS2_RC_SUCCESS
)
3702 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3703 "Failed to marshal PolicyAuthorizeNV command: %s", sym_Tss2_RC_Decode(rc
));
3705 if (offset
!= sizeof(command
))
3706 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3707 "Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset
);
3709 TPM2B_NV_PUBLIC public_info_copy
= *public_info
; /* Make a copy, since we must set TPMA_NV_WRITTEN for the calculation */
3710 public_info_copy
.nvPublic
.attributes
|= TPMA_NV_WRITTEN
;
3712 TPM2B_NAME name
= {};
3713 r
= tpm2_calculate_nv_index_name(&public_info_copy
.nvPublic
, &name
);
3717 struct iovec data
[] = {
3718 IOVEC_MAKE(buf
, offset
),
3719 IOVEC_MAKE(name
.name
, name
.size
),
3722 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3726 tpm2_log_debug_digest(digest
, "PolicyAuthorizeNV calculated digest");
3731 int tpm2_policy_authorize_nv(
3733 const Tpm2Handle
*session
,
3734 const Tpm2Handle
*nv_handle
,
3735 TPM2B_DIGEST
**ret_policy_digest
) {
3742 log_debug("Submitting AuthorizeNV policy.");
3744 rc
= sym_Esys_PolicyAuthorizeNV(
3747 nv_handle
->esys_handle
,
3748 session
->esys_handle
,
3752 if (rc
!= TSS2_RC_SUCCESS
)
3753 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3754 "Failed to add AuthorizeNV policy to TPM: %s",
3755 sym_Tss2_RC_Decode(rc
));
3757 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3762 const Tpm2Handle
*session
,
3763 const TPM2B_DIGEST
*branches
, size_t n_branches
,
3764 TPM2B_DIGEST
**ret_policy_digest
) {
3766 TPML_DIGEST hash_list
;
3772 if (n_branches
> ELEMENTSOF(hash_list
.digests
))
3775 log_debug("Submitting OR policy.");
3777 hash_list
= (TPML_DIGEST
) {
3778 .count
= n_branches
,
3781 memcpy(hash_list
.digests
, branches
, n_branches
* sizeof(TPM2B_DIGEST
));
3784 for (size_t i
= 0; i
< hash_list
.count
; i
++) {
3785 _cleanup_free_
char *h
= hexmem(hash_list
.digests
[i
].buffer
, hash_list
.digests
[i
].size
);
3786 log_debug("Submitting OR Branch #%zu: %s", i
, h
);
3789 rc
= sym_Esys_PolicyOR(
3791 session
->esys_handle
,
3796 if (rc
!= TSS2_RC_SUCCESS
)
3797 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3798 "Failed to add OR policy to TPM: %s",
3799 sym_Tss2_RC_Decode(rc
));
3801 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3804 /* Extend 'digest' with the PolicyOR calculated hash. */
3805 int tpm2_calculate_policy_or(const TPM2B_DIGEST
*branches
, size_t n_branches
, TPM2B_DIGEST
*digest
) {
3806 TPM2_CC command
= TPM2_CC_PolicyOR
;
3811 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3813 if (n_branches
== 0)
3815 if (n_branches
== 1)
3816 log_warning("PolicyOR with a single branch submitted, this is weird.");
3822 return log_error_errno(r
, "TPM2 support not installed: %m");
3824 uint8_t buf
[sizeof(command
)];
3827 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3828 if (rc
!= TSS2_RC_SUCCESS
)
3829 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3830 "Failed to marshal PolicyOR command: %s", sym_Tss2_RC_Decode(rc
));
3832 if (offset
!= sizeof(command
))
3833 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3834 "Offset 0x%zx wrong after marshalling PolicyOR command", offset
);
3835 _cleanup_free_
struct iovec
*data
= new(struct iovec
, 1 + n_branches
);
3839 data
[0] = IOVEC_MAKE(buf
, offset
);
3840 for (size_t i
= 0; i
< n_branches
; i
++) {
3841 data
[1 + i
] = IOVEC_MAKE((void*) branches
[i
].buffer
, branches
[i
].size
);
3843 if (DEBUG_LOGGING
) {
3844 _cleanup_free_
char *h
= hexmem(branches
[i
].buffer
, branches
[i
].size
);
3845 log_debug("OR Branch #%zu: %s", i
, h
);
3849 /* PolicyOR does not use the previous hash value; we must zero and then extend it. */
3850 zero(digest
->buffer
);
3852 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, 1 + n_branches
, /* extend= */ true);
3856 tpm2_log_debug_digest(digest
, "PolicyOR calculated digest");
3861 /* Extend 'digest' with the PolicyPCR calculated hash. */
3862 int tpm2_calculate_policy_pcr(
3863 const Tpm2PCRValue
*pcr_values
,
3864 size_t n_pcr_values
,
3865 TPM2B_DIGEST
*digest
) {
3867 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3871 assert(pcr_values
|| n_pcr_values
== 0);
3873 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3877 return log_debug_errno(r
, "TPM2 support not installed: %m");
3879 TPML_PCR_SELECTION pcr_selection
;
3880 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3882 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3884 return log_debug_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3886 TPM2B_DIGEST hash
= {};
3887 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3891 _cleanup_free_
uint8_t *buf
= NULL
;
3892 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3894 buf
= malloc(maxsize
);
3896 return log_oom_debug();
3898 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, maxsize
, &size
);
3899 if (rc
!= TSS2_RC_SUCCESS
)
3900 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3901 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc
));
3903 rc
= sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection
, buf
, maxsize
, &size
);
3904 if (rc
!= TSS2_RC_SUCCESS
)
3905 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3906 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc
));
3908 struct iovec data
[] = {
3909 IOVEC_MAKE(buf
, size
),
3910 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3912 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3916 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3921 int tpm2_policy_pcr(
3923 const Tpm2Handle
*session
,
3924 const TPML_PCR_SELECTION
*pcr_selection
,
3925 TPM2B_DIGEST
**ret_policy_digest
) {
3931 assert(pcr_selection
);
3933 log_debug("Submitting PCR hash policy.");
3935 rc
= sym_Esys_PolicyPCR(
3937 session
->esys_handle
,
3943 if (rc
!= TSS2_RC_SUCCESS
)
3944 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3945 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc
));
3947 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3950 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3951 int tpm2_calculate_policy_authorize(
3952 const TPM2B_PUBLIC
*public,
3953 const TPM2B_DIGEST
*policy_ref
,
3954 TPM2B_DIGEST
*digest
) {
3956 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3962 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3966 return log_debug_errno(r
, "TPM2 support not installed: %m");
3968 uint8_t buf
[sizeof(command
)];
3971 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3972 if (rc
!= TSS2_RC_SUCCESS
)
3973 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3974 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc
));
3976 if (offset
!= sizeof(command
))
3977 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3978 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
3980 TPM2B_NAME name
= {};
3981 r
= tpm2_calculate_pubkey_name(&public->publicArea
, &name
);
3985 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3986 zero(digest
->buffer
);
3988 struct iovec data
[] = {
3989 IOVEC_MAKE(buf
, offset
),
3990 IOVEC_MAKE(name
.name
, name
.size
),
3992 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3996 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3998 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
4000 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
4004 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
4009 static int tpm2_policy_authorize(
4011 const Tpm2Handle
*session
,
4012 TPML_PCR_SELECTION
*pcr_selection
,
4013 const TPM2B_PUBLIC
*public,
4016 JsonVariant
*signature_json
,
4017 TPM2B_DIGEST
**ret_policy_digest
) {
4024 assert(pcr_selection
);
4026 assert(fp
&& fp_size
> 0);
4028 log_debug("Adding PCR signature policy.");
4030 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
4031 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
4035 /* Acquire the "name" of what we just loaded */
4036 _cleanup_(Esys_Freep
) TPM2B_NAME
*pubkey_name
= NULL
;
4037 r
= tpm2_get_name(c
, pubkey_handle
, &pubkey_name
);
4041 /* If we have a signature, proceed with verifying the PCR digest */
4042 const TPMT_TK_VERIFIED
*check_ticket
;
4043 _cleanup_(Esys_Freep
) TPMT_TK_VERIFIED
*check_ticket_buffer
= NULL
;
4044 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*approved_policy
= NULL
;
4045 if (signature_json
) {
4046 r
= tpm2_policy_pcr(
4054 _cleanup_free_
void *signature_raw
= NULL
;
4055 size_t signature_size
;
4061 approved_policy
->buffer
,
4062 approved_policy
->size
,
4068 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
4069 * hence we need to do the SHA256 part ourselves, first */
4070 TPM2B_DIGEST signature_hash
= *approved_policy
;
4071 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, &signature_hash
);
4075 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
4077 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
4079 TPMT_SIGNATURE policy_signature
= {
4080 .sigAlg
= TPM2_ALG_RSASSA
,
4081 .signature
.rsassa
= {
4082 .hash
= TPM2_ALG_SHA256
,
4083 .sig
= TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw
, signature_size
),
4087 rc
= sym_Esys_VerifySignature(
4089 pubkey_handle
->esys_handle
,
4095 &check_ticket_buffer
);
4096 if (rc
!= TSS2_RC_SUCCESS
)
4097 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4098 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc
));
4100 check_ticket
= check_ticket_buffer
;
4102 /* When enrolling, we pass a NULL ticket */
4103 static const TPMT_TK_VERIFIED check_ticket_null
= {
4104 .tag
= TPM2_ST_VERIFIED
,
4105 .hierarchy
= TPM2_RH_OWNER
,
4108 check_ticket
= &check_ticket_null
;
4111 rc
= sym_Esys_PolicyAuthorize(
4113 session
->esys_handle
,
4118 /* policyRef= */ &(const TPM2B_NONCE
) {},
4121 if (rc
!= TSS2_RC_SUCCESS
)
4122 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4123 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc
));
4125 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
4128 /* Extend 'digest' with the calculated policy hash. */
4129 int tpm2_calculate_sealing_policy(
4130 const Tpm2PCRValue
*pcr_values
,
4131 size_t n_pcr_values
,
4132 const TPM2B_PUBLIC
*public,
4134 const Tpm2PCRLockPolicy
*pcrlock_policy
,
4135 TPM2B_DIGEST
*digest
) {
4139 assert(pcr_values
|| n_pcr_values
== 0);
4142 if (public && pcrlock_policy
)
4143 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Policies with both signed PCR and pcrlock are currently not supported.");
4146 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
4151 if (pcrlock_policy
) {
4152 TPM2B_NV_PUBLIC nv_public
;
4154 r
= tpm2_unmarshal_nv_public(
4155 pcrlock_policy
->nv_public
.iov_base
,
4156 pcrlock_policy
->nv_public
.iov_len
,
4161 r
= tpm2_calculate_policy_authorize_nv(&nv_public
, digest
);
4166 if (n_pcr_values
> 0) {
4167 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
4173 r
= tpm2_calculate_policy_auth_value(digest
);
4181 static int tpm2_build_sealing_policy(
4183 const Tpm2Handle
*session
,
4184 uint32_t hash_pcr_mask
,
4186 const TPM2B_PUBLIC
*public,
4189 uint32_t pubkey_pcr_mask
,
4190 JsonVariant
*signature_json
,
4192 const Tpm2PCRLockPolicy
*pcrlock_policy
,
4193 TPM2B_DIGEST
**ret_policy_digest
) {
4199 assert(pubkey_pcr_mask
== 0 || public);
4201 log_debug("Building sealing policy.");
4203 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
4204 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
4208 log_debug("Selected TPM2 PCRs are not initialized on this system.");
4211 if (pubkey_pcr_mask
!= 0 && pcrlock_policy
)
4212 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Policies with both signed PCR and pcrlock are currently not supported.");
4214 if (pubkey_pcr_mask
!= 0) {
4215 TPML_PCR_SELECTION pcr_selection
;
4216 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
4217 r
= tpm2_policy_authorize(c
, session
, &pcr_selection
, public, fp
, fp_size
, signature_json
, NULL
);
4222 if (pcrlock_policy
) {
4223 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*nv_handle
= NULL
;
4225 r
= tpm2_policy_super_pcr(
4228 &pcrlock_policy
->prediction
,
4229 pcrlock_policy
->algorithm
);
4233 r
= tpm2_deserialize(
4235 pcrlock_policy
->nv_handle
.iov_base
,
4236 pcrlock_policy
->nv_handle
.iov_len
,
4241 r
= tpm2_policy_authorize_nv(
4250 if (hash_pcr_mask
!= 0) {
4251 TPML_PCR_SELECTION pcr_selection
;
4252 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
4253 r
= tpm2_policy_pcr(c
, session
, &pcr_selection
, NULL
);
4259 r
= tpm2_policy_auth_value(c
, session
, NULL
);
4264 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
4272 static const struct {
4273 TPM2_ECC_CURVE tpm2_ecc_curve_id
;
4274 int openssl_ecc_curve_id
;
4275 } tpm2_openssl_ecc_curve_table
[] = {
4276 { TPM2_ECC_NIST_P192
, NID_X9_62_prime192v1
, },
4277 { TPM2_ECC_NIST_P224
, NID_secp224r1
, },
4278 { TPM2_ECC_NIST_P256
, NID_X9_62_prime256v1
, },
4279 { TPM2_ECC_NIST_P384
, NID_secp384r1
, },
4280 { TPM2_ECC_NIST_P521
, NID_secp521r1
, },
4281 { TPM2_ECC_SM2_P256
, NID_sm2
, },
4284 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id
, TPM2_ECC_CURVE
*ret
) {
4287 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
4288 if (t
->openssl_ecc_curve_id
== openssl_ecc_curve_id
) {
4289 *ret
= t
->tpm2_ecc_curve_id
;
4293 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4294 "OpenSSL ECC curve id %d not supported.", openssl_ecc_curve_id
);
4297 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id
, int *ret
) {
4300 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
4301 if (t
->tpm2_ecc_curve_id
== tpm2_ecc_curve_id
) {
4302 *ret
= t
->openssl_ecc_curve_id
;
4306 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4307 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id
);
4310 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
4312 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
4318 const TPMT_PUBLIC
*p
= &public->publicArea
;
4320 case TPM2_ALG_ECC
: {
4322 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
4326 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
4327 return ecc_pkey_from_curve_x_y(
4335 case TPM2_ALG_RSA
: {
4336 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4337 * zero indicates that the exponent is the default of 2^16 + 1". */
4338 uint32_t exponent
= htobe32(p
->parameters
.rsaDetail
.exponent
?: TPM2_RSA_DEFAULT_EXPONENT
);
4339 return rsa_pkey_from_n_e(
4340 p
->unique
.rsa
.buffer
,
4347 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4348 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
4352 /* Be careful before changing anything in this function, as the TPM key "name" is calculated using the entire
4353 * TPMT_PUBLIC (after marshalling), and that "name" is used (for example) to calculate the policy hash for
4354 * the Authorize policy. So we must ensure this conversion of a PEM to TPM2B_PUBLIC does not change the
4355 * "name", because it would break unsealing of previously-sealed objects that used (for example)
4356 * tpm2_calculate_policy_authorize(). See bug #30546. */
4357 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY
*pkey
, TPM2B_PUBLIC
*ret
) {
4363 TPMT_PUBLIC
public = {
4364 .nameAlg
= TPM2_ALG_SHA256
,
4365 .objectAttributes
= TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
,
4366 .parameters
.asymDetail
= {
4367 .symmetric
.algorithm
= TPM2_ALG_NULL
,
4368 .scheme
.scheme
= TPM2_ALG_NULL
,
4372 #if OPENSSL_VERSION_MAJOR >= 3
4373 key_id
= EVP_PKEY_get_id(pkey
);
4375 key_id
= EVP_PKEY_id(pkey
);
4380 public.type
= TPM2_ALG_ECC
;
4383 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
4384 size_t x_size
, y_size
;
4385 r
= ecc_pkey_to_curve_x_y(pkey
, &curve_id
, &x
, &x_size
, &y
, &y_size
);
4387 return log_debug_errno(r
, "Could not get ECC key curve/x/y: %m");
4389 TPM2_ECC_CURVE curve
;
4390 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
4394 public.parameters
.eccDetail
.curveID
= curve
;
4396 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
4398 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
4400 return log_debug_errno(r
, "ECC key x size %zu too large.", x_size
);
4402 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
4404 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
4406 return log_debug_errno(r
, "ECC key y size %zu too large.", y_size
);
4408 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
4412 case EVP_PKEY_RSA
: {
4413 public.type
= TPM2_ALG_RSA
;
4415 _cleanup_free_
void *n
= NULL
, *e
= NULL
;
4416 size_t n_size
, e_size
;
4417 r
= rsa_pkey_to_n_e(pkey
, &n
, &n_size
, &e
, &e_size
);
4419 return log_debug_errno(r
, "Could not get RSA key n/e: %m");
4421 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
4423 return log_debug_errno(r
, "RSA key n size %zu too large.", n_size
);
4425 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
4426 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
4428 if (sizeof(uint32_t) < e_size
)
4429 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
4430 "RSA key e size %zu too large.", e_size
);
4432 uint32_t exponent
= 0;
4433 memcpy(&exponent
, e
, e_size
);
4434 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
4436 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4437 * zero indicates that the exponent is the default of 2^16 + 1". However, we have no reason
4438 * to special case it in our PEM->TPM2B_PUBLIC conversion, and doing so could break backwards
4439 * compatibility, so even if it is the "default" value of 0x10001, we do not set it to 0. */
4440 public.parameters
.rsaDetail
.exponent
= exponent
;
4445 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4446 "EVP_PKEY type %d not supported.", key_id
);
4449 *ret
= (TPM2B_PUBLIC
) {
4450 .size
= sizeof(public),
4451 .publicArea
= public,
4458 int tpm2_tpm2b_public_to_fingerprint(
4459 const TPM2B_PUBLIC
*public,
4460 void **ret_fingerprint
,
4461 size_t *ret_fingerprint_size
) {
4467 assert(ret_fingerprint
);
4468 assert(ret_fingerprint_size
);
4470 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4471 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
4475 /* Hardcode fingerprint to SHA256 */
4476 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
4478 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4482 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
4489 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4490 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
4494 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
4496 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4500 /* Marshal the public, private, and seed objects into a single nonstandard 'blob'. The public and private
4501 * objects are required, while the seed is optional. This is not a (publicly) standard format, this is
4502 * specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
4503 * tpm2_unmarshal_blob(). */
4504 int tpm2_marshal_blob(
4505 const TPM2B_PUBLIC
*public,
4506 const TPM2B_PRIVATE
*private,
4507 const TPM2B_ENCRYPTED_SECRET
*seed
,
4509 size_t *ret_blob_size
) {
4516 assert(ret_blob_size
);
4518 size_t max_size
= sizeof(*private) + sizeof(*public);
4520 max_size
+= sizeof(*seed
);
4522 _cleanup_free_
void *blob
= malloc(max_size
);
4524 return log_oom_debug();
4526 size_t blob_size
= 0;
4527 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
4528 if (rc
!= TSS2_RC_SUCCESS
)
4529 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4530 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
4532 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
4533 if (rc
!= TSS2_RC_SUCCESS
)
4534 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4535 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
4538 rc
= sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal(seed
, blob
, max_size
, &blob_size
);
4539 if (rc
!= TSS2_RC_SUCCESS
)
4540 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4541 "Failed to marshal encrypted seed: %s", sym_Tss2_RC_Decode(rc
));
4544 *ret_blob
= TAKE_PTR(blob
);
4545 *ret_blob_size
= blob_size
;
4550 /* Unmarshal the 'blob' into public, private, and seed objects. The public and private objects are required
4551 * in the 'blob', while the seed is optional. This is not a (publicly) standard format, this is specific to
4552 * how we currently store the sealed object. This expects the 'blob' to have been created by
4553 * tpm2_marshal_blob(). */
4554 int tpm2_unmarshal_blob(
4557 TPM2B_PUBLIC
*ret_public
,
4558 TPM2B_PRIVATE
*ret_private
,
4559 TPM2B_ENCRYPTED_SECRET
*ret_seed
) {
4565 assert(ret_private
);
4568 TPM2B_PRIVATE
private = {};
4570 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob
, blob_size
, &offset
, &private);
4571 if (rc
!= TSS2_RC_SUCCESS
)
4572 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4573 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
4575 TPM2B_PUBLIC
public = {};
4576 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob
, blob_size
, &offset
, &public);
4577 if (rc
!= TSS2_RC_SUCCESS
)
4578 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4579 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
4581 TPM2B_ENCRYPTED_SECRET seed
= {};
4582 if (blob_size
> offset
) {
4583 rc
= sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal(blob
, blob_size
, &offset
, &seed
);
4584 if (rc
!= TSS2_RC_SUCCESS
)
4585 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4586 "Failed to unmarshal encrypted seed: %s", sym_Tss2_RC_Decode(rc
));
4589 *ret_public
= public;
4590 *ret_private
= private;
4596 /* Calculate a serialized handle. Once the upstream tpm2-tss library provides an api to do this, we can
4597 * remove this function. The addition of this functionality in tpm2-tss may be tracked here:
4598 * https://github.com/tpm2-software/tpm2-tss/issues/2575 */
4599 int tpm2_calculate_serialize(
4601 const TPM2B_NAME
*name
,
4602 const TPM2B_PUBLIC
*public,
4603 void **ret_serialized
,
4604 size_t *ret_serialized_size
) {
4610 assert(ret_serialized
);
4611 assert(ret_serialized_size
);
4613 size_t max_size
= sizeof(TPM2_HANDLE
) + sizeof(TPM2B_NAME
) + sizeof(uint32_t) + sizeof(TPM2B_PUBLIC
);
4614 _cleanup_free_
void *serialized
= malloc(max_size
);
4616 return log_oom_debug();
4618 size_t serialized_size
= 0;
4619 rc
= sym_Tss2_MU_TPM2_HANDLE_Marshal(handle
, serialized
, max_size
, &serialized_size
);
4620 if (rc
!= TSS2_RC_SUCCESS
)
4621 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4622 "Failed to marshal tpm handle: %s", sym_Tss2_RC_Decode(rc
));
4624 rc
= sym_Tss2_MU_TPM2B_NAME_Marshal(name
, serialized
, max_size
, &serialized_size
);
4625 if (rc
!= TSS2_RC_SUCCESS
)
4626 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4627 "Failed to marshal name: %s", sym_Tss2_RC_Decode(rc
));
4629 /* This is defined (non-publicly) in the tpm2-tss source as IESYSC_KEY_RSRC, to a value of "1". */
4630 rc
= sym_Tss2_MU_UINT32_Marshal(UINT32_C(1), serialized
, max_size
, &serialized_size
);
4631 if (rc
!= TSS2_RC_SUCCESS
)
4632 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4633 "Failed to marshal esys resource id: %s", sym_Tss2_RC_Decode(rc
));
4635 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, serialized
, max_size
, &serialized_size
);
4636 if (rc
!= TSS2_RC_SUCCESS
)
4637 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4638 "Failed to marshal public: %s", sym_Tss2_RC_Decode(rc
));
4640 *ret_serialized
= TAKE_PTR(serialized
);
4641 *ret_serialized_size
= serialized_size
;
4646 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
4647 * across restarts of the TPM or reboots (assuming the handle is persistent). */
4650 const Tpm2Handle
*handle
,
4651 void **ret_serialized
,
4652 size_t *ret_serialized_size
) {
4658 assert(ret_serialized
);
4659 assert(ret_serialized_size
);
4661 _cleanup_(Esys_Freep
) unsigned char *serialized
= NULL
;
4663 rc
= sym_Esys_TR_Serialize(c
->esys_context
, handle
->esys_handle
, &serialized
, &size
);
4664 if (rc
!= TSS2_RC_SUCCESS
)
4665 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4666 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc
));
4668 *ret_serialized
= TAKE_PTR(serialized
);
4669 *ret_serialized_size
= size
;
4674 int tpm2_deserialize(
4676 const void *serialized
,
4677 size_t serialized_size
,
4678 Tpm2Handle
**ret_handle
) {
4687 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
4688 r
= tpm2_handle_new(c
, &handle
);
4692 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
4693 handle
->flush
= false;
4695 rc
= sym_Esys_TR_Deserialize(c
->esys_context
, serialized
, serialized_size
, &handle
->esys_handle
);
4696 if (rc
!= TSS2_RC_SUCCESS
)
4697 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4698 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc
));
4700 *ret_handle
= TAKE_PTR(handle
);
4707 /* KDFa() as defined by the TPM spec. */
4708 static int tpm2_kdfa(
4709 TPMI_ALG_HASH hash_alg
,
4713 const void *context
,
4717 size_t *ret_key_len
) {
4723 assert(context
|| context_len
== 0);
4725 assert(bits
<= SIZE_MAX
- 7);
4727 assert(ret_key_len
);
4729 log_debug("Calculating KDFa().");
4731 size_t len
= DIV_ROUND_UP(bits
, 8);
4733 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4737 _cleanup_free_
void *buf
= NULL
;
4738 r
= kdf_kb_hmac_derive(
4754 /* If the number of bits results in a partial byte, the TPM spec requires we zero the unrequested
4755 * bits in the MSB (i.e. at index 0). From the spec Part 1 ("Architecture") section on Key
4756 * Derivation Function, specifically KDFa():
4758 * "The implied return from this function is a sequence of octets with a length equal to (bits + 7) /
4759 * 8. If bits is not an even multiple of 8, then the returned value occupies the least significant
4760 * bits of the returned octet array, and the additional, high-order bits in the 0th octet are
4761 * CLEAR. The unused bits of the most significant octet (MSO) are masked off and not shifted." */
4762 size_t partial
= bits
% 8;
4764 ((uint8_t*) buf
)[0] &= 0xffu
>> (8 - partial
);
4766 *ret_key
= TAKE_PTR(buf
);
4772 /* KDFe() as defined by the TPM spec. */
4773 static int tpm2_kdfe(
4774 TPMI_ALG_HASH hash_alg
,
4775 const void *shared_secret
,
4776 size_t shared_secret_len
,
4778 const void *context_u
,
4779 size_t context_u_size
,
4780 const void *context_v
,
4781 size_t context_v_size
,
4784 size_t *ret_key_len
) {
4788 assert(shared_secret
);
4793 assert(bits
<= SIZE_MAX
- 7);
4795 assert(ret_key_len
);
4797 log_debug("Calculating KDFe().");
4799 size_t len
= DIV_ROUND_UP(bits
, 8);
4801 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4805 size_t info_len
= strlen(label
) + 1 + context_u_size
+ context_v_size
;
4806 _cleanup_free_
void *info
= malloc(info_len
);
4808 return log_oom_debug();
4810 void *end
= mempcpy(mempcpy(stpcpy(info
, label
) + 1, context_u
, context_u_size
), context_v
, context_v_size
);
4811 /* assert we copied exactly the right amount that we allocated */
4812 assert(end
> info
&& (uintptr_t) end
- (uintptr_t) info
== info_len
);
4814 _cleanup_free_
void *buf
= NULL
;
4828 *ret_key
= TAKE_PTR(buf
);
4834 static int tpm2_calculate_seal_public(
4835 const TPM2B_PUBLIC
*parent
,
4836 const TPMA_OBJECT
*attributes
,
4837 const TPM2B_DIGEST
*policy
,
4838 const TPM2B_DIGEST
*seed
,
4841 TPM2B_PUBLIC
*ret
) {
4850 log_debug("Calculating public part of sealed object.");
4852 struct iovec data
[] = {
4853 IOVEC_MAKE((void*) seed
->buffer
, seed
->size
),
4854 IOVEC_MAKE((void*) secret
, secret_size
),
4856 TPM2B_DIGEST unique
;
4857 r
= tpm2_digest_many(
4858 parent
->publicArea
.nameAlg
,
4862 /* extend= */ false);
4866 *ret
= (TPM2B_PUBLIC
) {
4867 .size
= sizeof(TPMT_PUBLIC
),
4869 .type
= TPM2_ALG_KEYEDHASH
,
4870 .nameAlg
= parent
->publicArea
.nameAlg
,
4871 .objectAttributes
= attributes
? *attributes
: 0,
4872 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, unique
.size
),
4873 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
4874 .unique
.keyedHash
= unique
,
4881 static int tpm2_calculate_seal_private(
4882 const TPM2B_PUBLIC
*parent
,
4883 const TPM2B_NAME
*name
,
4885 const TPM2B_DIGEST
*seed
,
4888 TPM2B_PRIVATE
*ret
) {
4899 log_debug("Calculating private part of sealed object.");
4901 _cleanup_free_
void *storage_key
= NULL
;
4902 size_t storage_key_size
;
4903 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4909 (size_t) parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
4913 return log_debug_errno(r
, "Could not calculate storage key KDFa: %m");
4915 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
4919 size_t bits
= (size_t) r
* 8;
4921 _cleanup_free_
void *integrity_key
= NULL
;
4922 size_t integrity_key_size
;
4923 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4927 /* context= */ NULL
,
4931 &integrity_key_size
);
4933 return log_debug_errno(r
, "Could not calculate integrity key KDFa: %m");
4935 TPM2B_AUTH auth
= {};
4937 r
= tpm2_auth_value_from_pin(parent
->publicArea
.nameAlg
, pin
, &auth
);
4942 TPM2B_SENSITIVE sensitive
= {
4943 .size
= sizeof(TPMT_SENSITIVE
),
4945 .sensitiveType
= TPM2_ALG_KEYEDHASH
,
4948 .sensitive
.bits
= TPM2B_SENSITIVE_DATA_MAKE(secret
, secret_size
),
4952 _cleanup_free_
void *marshalled_sensitive
= malloc(sizeof(sensitive
));
4953 if (!marshalled_sensitive
)
4954 return log_oom_debug();
4956 size_t marshalled_sensitive_size
= 0;
4957 rc
= sym_Tss2_MU_TPM2B_SENSITIVE_Marshal(
4959 marshalled_sensitive
,
4961 &marshalled_sensitive_size
);
4962 if (rc
!= TSS2_RC_SUCCESS
)
4963 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4964 "Failed to marshal sensitive: %s", sym_Tss2_RC_Decode(rc
));
4966 const char *sym_alg
= tpm2_sym_alg_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.algorithm
);
4970 const char *sym_mode
= tpm2_sym_mode_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.mode
.sym
);
4974 _cleanup_free_
void *encrypted_sensitive
= NULL
;
4975 size_t encrypted_sensitive_size
;
4978 parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
4980 storage_key
, storage_key_size
,
4981 /* iv= */ NULL
, /* n_iv= */ 0,
4982 marshalled_sensitive
, marshalled_sensitive_size
,
4983 &encrypted_sensitive
, &encrypted_sensitive_size
);
4987 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
4991 _cleanup_free_
void *hmac_buffer
= NULL
;
4992 size_t hmac_size
= 0;
4993 struct iovec hmac_data
[] = {
4994 IOVEC_MAKE((void*) encrypted_sensitive
, encrypted_sensitive_size
),
4995 IOVEC_MAKE((void*) name
->name
, name
->size
),
4997 r
= openssl_hmac_many(
5002 ELEMENTSOF(hmac_data
),
5008 TPM2B_DIGEST outer_hmac
= TPM2B_DIGEST_MAKE(hmac_buffer
, hmac_size
);
5010 TPM2B_PRIVATE
private = {};
5011 size_t private_size
= 0;
5012 rc
= sym_Tss2_MU_TPM2B_DIGEST_Marshal(
5015 sizeof(private.buffer
),
5017 if (rc
!= TSS2_RC_SUCCESS
)
5018 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5019 "Failed to marshal digest: %s", sym_Tss2_RC_Decode(rc
));
5020 private.size
= private_size
;
5022 assert(sizeof(private.buffer
) - private.size
>= encrypted_sensitive_size
);
5023 memcpy_safe(&private.buffer
[private.size
], encrypted_sensitive
, encrypted_sensitive_size
);
5024 private.size
+= encrypted_sensitive_size
;
5031 static int tpm2_calculate_seal_rsa_seed(
5032 const TPM2B_PUBLIC
*parent
,
5034 size_t *ret_seed_size
,
5035 void **ret_encrypted_seed
,
5036 size_t *ret_encrypted_seed_size
) {
5042 assert(ret_seed_size
);
5043 assert(ret_encrypted_seed
);
5044 assert(ret_encrypted_seed_size
);
5046 log_debug("Calculating encrypted seed for RSA sealed object.");
5048 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
5049 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
5051 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
5053 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
5057 size_t seed_size
= (size_t) r
;
5059 _cleanup_free_
void *seed
= malloc(seed_size
);
5061 return log_oom_debug();
5063 r
= crypto_random_bytes(seed
, seed_size
);
5065 return log_debug_errno(r
, "Failed to generate random seed: %m");
5067 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
5071 _cleanup_free_
void *encrypted_seed
= NULL
;
5072 size_t encrypted_seed_size
;
5073 r
= rsa_oaep_encrypt_bytes(
5080 &encrypted_seed_size
);
5082 return log_debug_errno(r
, "Could not RSA-OAEP encrypt random seed: %m");
5084 *ret_seed
= TAKE_PTR(seed
);
5085 *ret_seed_size
= seed_size
;
5086 *ret_encrypted_seed
= TAKE_PTR(encrypted_seed
);
5087 *ret_encrypted_seed_size
= encrypted_seed_size
;
5092 static int tpm2_calculate_seal_ecc_seed(
5093 const TPM2B_PUBLIC
*parent
,
5095 size_t *ret_seed_size
,
5096 void **ret_encrypted_seed
,
5097 size_t *ret_encrypted_seed_size
) {
5104 assert(ret_seed_size
);
5105 assert(ret_encrypted_seed
);
5106 assert(ret_encrypted_seed_size
);
5108 log_debug("Calculating encrypted seed for ECC sealed object.");
5110 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
5111 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
5113 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
5116 r
= ecc_pkey_to_curve_x_y(
5119 /* ret_x= */ NULL
, /* ret_x_size= */ 0,
5120 /* ret_y= */ NULL
, /* ret_y_size= */ 0);
5124 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
5125 r
= ecc_pkey_new(curve_id
, &pkey
);
5129 _cleanup_free_
void *shared_secret
= NULL
;
5130 size_t shared_secret_size
;
5131 r
= ecc_ecdh(pkey
, parent_pkey
, &shared_secret
, &shared_secret_size
);
5133 return log_debug_errno(r
, "Could not generate ECC shared secret: %m");
5135 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
5136 size_t x_size
, y_size
;
5137 r
= ecc_pkey_to_curve_x_y(pkey
, /* curve_id= */ NULL
, &x
, &x_size
, &y
, &y_size
);
5139 return log_debug_errno(r
, "Could not get ECC get x/y: %m");
5141 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
5143 return log_debug_errno(r
, "ECC point x size %zu is too large: %m", x_size
);
5145 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
5147 return log_debug_errno(r
, "ECC point y size %zu is too large: %m", y_size
);
5149 TPMS_ECC_POINT point
= {
5150 .x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
),
5151 .y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
),
5154 _cleanup_free_
void *encrypted_seed
= malloc(sizeof(point
));
5155 if (!encrypted_seed
)
5156 return log_oom_debug();
5158 size_t encrypted_seed_size
= 0;
5159 rc
= sym_Tss2_MU_TPMS_ECC_POINT_Marshal(&point
, encrypted_seed
, sizeof(point
), &encrypted_seed_size
);
5160 if (rc
!= TPM2_RC_SUCCESS
)
5161 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5162 "Failed to marshal ECC point: %s", sym_Tss2_RC_Decode(rc
));
5164 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
5168 size_t bits
= (size_t) r
* 8;
5170 _cleanup_free_
void *seed
= NULL
;
5171 size_t seed_size
= 0; /* Explicit initialization to appease gcc */
5172 r
= tpm2_kdfe(parent
->publicArea
.nameAlg
,
5178 parent
->publicArea
.unique
.ecc
.x
.buffer
,
5179 parent
->publicArea
.unique
.ecc
.x
.size
,
5184 return log_debug_errno(r
, "Could not calculate KDFe: %m");
5186 *ret_seed
= TAKE_PTR(seed
);
5187 *ret_seed_size
= seed_size
;
5188 *ret_encrypted_seed
= TAKE_PTR(encrypted_seed
);
5189 *ret_encrypted_seed_size
= encrypted_seed_size
;
5194 static int tpm2_calculate_seal_seed(
5195 const TPM2B_PUBLIC
*parent
,
5196 TPM2B_DIGEST
*ret_seed
,
5197 TPM2B_ENCRYPTED_SECRET
*ret_encrypted_seed
) {
5203 assert(ret_encrypted_seed
);
5205 log_debug("Calculating encrypted seed for sealed object.");
5207 _cleanup_free_
void *seed
= NULL
, *encrypted_seed
= NULL
;
5208 size_t seed_size
= 0, encrypted_seed_size
= 0; /* Explicit initialization to appease gcc */
5209 if (parent
->publicArea
.type
== TPM2_ALG_RSA
)
5210 r
= tpm2_calculate_seal_rsa_seed(parent
, &seed
, &seed_size
, &encrypted_seed
, &encrypted_seed_size
);
5211 else if (parent
->publicArea
.type
== TPM2_ALG_ECC
)
5212 r
= tpm2_calculate_seal_ecc_seed(parent
, &seed
, &seed_size
, &encrypted_seed
, &encrypted_seed_size
);
5214 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5215 "Unsupported parent key type 0x%" PRIx16
, parent
->publicArea
.type
);
5217 return log_debug_errno(r
, "Could not calculate encrypted seed: %m");
5219 *ret_seed
= TPM2B_DIGEST_MAKE(seed
, seed_size
);
5220 *ret_encrypted_seed
= TPM2B_ENCRYPTED_SECRET_MAKE(encrypted_seed
, encrypted_seed_size
);
5225 #endif /* HAVE_OPENSSL */
5227 int tpm2_calculate_seal(
5228 TPM2_HANDLE parent_handle
,
5229 const TPM2B_PUBLIC
*parent_public
,
5230 const TPMA_OBJECT
*attributes
,
5231 const struct iovec
*secret
,
5232 const TPM2B_DIGEST
*policy
,
5234 struct iovec
*ret_secret
,
5235 struct iovec
*ret_blob
,
5236 struct iovec
*ret_serialized_parent
) {
5241 assert(parent_public
);
5242 assert(iovec_is_valid(secret
));
5243 assert(secret
|| ret_secret
);
5244 assert(!(secret
&& ret_secret
)); /* Either provide a secret, or we create one, but not both */
5246 assert(ret_serialized_parent
);
5248 log_debug("Calculating sealed object.");
5250 /* Default to the SRK. */
5251 if (parent_handle
== 0)
5252 parent_handle
= TPM2_SRK_HANDLE
;
5254 switch (TPM2_HANDLE_TYPE(parent_handle
)) {
5255 case TPM2_HT_PERSISTENT
:
5256 case TPM2_HT_NV_INDEX
:
5258 case TPM2_HT_TRANSIENT
:
5259 log_warning("Handle is transient, sealed secret may not be recoverable.");
5262 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5263 "Handle 0x%" PRIx32
" not persistent, transient, or NV.",
5267 _cleanup_(iovec_done_erase
) struct iovec generated_secret
= {};
5269 /* No secret provided, generate a random secret. We use SHA256 digest length, though it can
5270 * be up to TPM2_MAX_SEALED_DATA. The secret length is not limited to the nameAlg hash
5272 generated_secret
.iov_len
= TPM2_SHA256_DIGEST_SIZE
;
5273 generated_secret
.iov_base
= malloc(generated_secret
.iov_len
);
5274 if (!generated_secret
.iov_base
)
5275 return log_oom_debug();
5277 r
= crypto_random_bytes(generated_secret
.iov_base
, generated_secret
.iov_len
);
5279 return log_debug_errno(r
, "Failed to generate secret key: %m");
5281 secret
= &generated_secret
;
5284 if (secret
->iov_len
> TPM2_MAX_SEALED_DATA
)
5285 return log_debug_errno(SYNTHETIC_ERRNO(EOVERFLOW
),
5286 "Secret size %zu too large, limit is %d bytes.",
5287 secret
->iov_len
, TPM2_MAX_SEALED_DATA
);
5289 TPM2B_DIGEST random_seed
;
5290 TPM2B_ENCRYPTED_SECRET seed
;
5291 r
= tpm2_calculate_seal_seed(parent_public
, &random_seed
, &seed
);
5295 TPM2B_PUBLIC
public;
5296 r
= tpm2_calculate_seal_public(parent_public
, attributes
, policy
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &public);
5301 r
= tpm2_calculate_pubkey_name(&public.publicArea
, &name
);
5305 TPM2B_PRIVATE
private;
5306 r
= tpm2_calculate_seal_private(parent_public
, &name
, pin
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &private);
5310 _cleanup_(iovec_done
) struct iovec blob
= {};
5311 r
= tpm2_marshal_blob(&public, &private, &seed
, &blob
.iov_base
, &blob
.iov_len
);
5313 return log_debug_errno(r
, "Could not create sealed blob: %m");
5315 TPM2B_NAME parent_name
;
5316 r
= tpm2_calculate_pubkey_name(&parent_public
->publicArea
, &parent_name
);
5320 _cleanup_(iovec_done
) struct iovec serialized_parent
= {};
5321 r
= tpm2_calculate_serialize(
5325 &serialized_parent
.iov_base
,
5326 &serialized_parent
.iov_len
);
5331 *ret_secret
= TAKE_STRUCT(generated_secret
);
5332 *ret_blob
= TAKE_STRUCT(blob
);
5333 *ret_serialized_parent
= TAKE_STRUCT(serialized_parent
);
5336 #else /* HAVE_OPENSSL */
5337 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
5341 int tpm2_seal(Tpm2Context
*c
,
5342 uint32_t seal_key_handle
,
5343 const TPM2B_DIGEST
*policy
,
5345 struct iovec
*ret_secret
,
5346 struct iovec
*ret_blob
,
5347 uint16_t *ret_primary_alg
,
5348 struct iovec
*ret_srk
) {
5350 uint16_t primary_alg
= 0;
5356 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
5357 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
5358 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
5359 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
5360 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
5361 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
5362 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
5363 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
5364 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
5365 * LUKS2 JSON header.
5367 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
5368 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
5369 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
5370 * binding the unlocking to the TPM2 chip. */
5372 usec_t start
= now(CLOCK_MONOTONIC
);
5374 TPMA_OBJECT hmac_attributes
=
5375 TPMA_OBJECT_FIXEDTPM
|
5376 TPMA_OBJECT_FIXEDPARENT
;
5378 /* If protected by PIN, a user-selected low-entropy password, enable DA protection.
5379 Without a PIN, the key's left protected only by a PCR policy, which does not benefit
5380 from DA protection. */
5381 hmac_attributes
|= pin
? 0 : TPMA_OBJECT_NODA
;
5383 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
5384 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
5385 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
5386 TPMT_PUBLIC hmac_template
= {
5387 .type
= TPM2_ALG_KEYEDHASH
,
5388 .nameAlg
= TPM2_ALG_SHA256
,
5389 .objectAttributes
= hmac_attributes
,
5390 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
5391 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
5392 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
5395 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
5396 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
5399 CLEANUP_ERASE(hmac_sensitive
);
5402 r
= tpm2_auth_value_from_pin(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
5407 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
5409 (void) tpm2_credit_random(c
);
5411 log_debug("Generating secret key data.");
5413 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
5415 return log_debug_errno(r
, "Failed to generate secret key: %m");
5417 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
5419 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
5421 if (IN_SET(seal_key_handle
, 0, TPM2_SRK_HANDLE
)) {
5422 r
= tpm2_get_or_create_srk(
5424 /* session= */ NULL
,
5426 /* ret_name= */ NULL
,
5427 /* ret_qname= */ NULL
,
5431 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle
), TPM2_HT_TRANSIENT
, TPM2_HT_PERSISTENT
)) {
5432 r
= tpm2_index_to_handle(
5435 /* session= */ NULL
,
5437 /* ret_name= */ NULL
,
5438 /* ret_qname= */ NULL
,
5443 /* We do NOT automatically create anything other than the SRK */
5444 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
5445 "No handle found at index 0x%" PRIx32
, seal_key_handle
);
5447 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5448 "Seal key handle 0x%" PRIx32
" is neither transient nor persistent.",
5451 primary_alg
= primary_public
->publicArea
.type
;
5453 if (seal_key_handle
!= 0)
5454 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
5456 /* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
5457 primary_alg
= TPM2_ALG_ECC
;
5459 TPM2B_PUBLIC
template = {
5460 .size
= sizeof(TPMT_PUBLIC
),
5462 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5464 return log_debug_errno(r
, "Could not get legacy ECC template: %m");
5466 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
5467 primary_alg
= TPM2_ALG_RSA
;
5469 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5471 return log_debug_errno(r
, "Could not get legacy RSA template: %m");
5473 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
))
5474 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5475 "TPM does not support either ECC or RSA legacy template.");
5478 r
= tpm2_create_primary(
5480 /* session= */ NULL
,
5482 /* sensitive= */ NULL
,
5483 /* ret_public= */ NULL
,
5489 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5490 r
= tpm2_make_encryption_session(c
, primary_handle
, /* bind_key= */ NULL
, &encryption_session
);
5494 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
5495 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
5496 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
5500 _cleanup_(iovec_done_erase
) struct iovec secret
= {};
5501 secret
.iov_base
= memdup(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
5502 if (!secret
.iov_base
)
5503 return log_oom_debug();
5504 secret
.iov_len
= hmac_sensitive
.data
.size
;
5506 log_debug("Marshalling private and public part of HMAC key.");
5508 _cleanup_(iovec_done
) struct iovec blob
= {};
5509 r
= tpm2_marshal_blob(public, private, /* seed= */ NULL
, &blob
.iov_base
, &blob
.iov_len
);
5511 return log_debug_errno(r
, "Could not create sealed blob: %m");
5514 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5517 _cleanup_(iovec_done
) struct iovec srk
= {};
5518 _cleanup_(Esys_Freep
) void *tmp
= NULL
;
5521 r
= tpm2_serialize(c
, primary_handle
, &tmp
, &tmp_size
);
5526 * make a copy since we don't want the caller to understand that
5527 * ESYS allocated the pointer. It would make tracking what deallocator
5528 * to use for srk in which context a PITA.
5530 srk
.iov_base
= memdup(tmp
, tmp_size
);
5532 return log_oom_debug();
5533 srk
.iov_len
= tmp_size
;
5535 *ret_srk
= TAKE_STRUCT(srk
);
5538 *ret_secret
= TAKE_STRUCT(secret
);
5539 *ret_blob
= TAKE_STRUCT(blob
);
5541 if (ret_primary_alg
)
5542 *ret_primary_alg
= primary_alg
;
5547 #define RETRY_UNSEAL_MAX 30u
5549 int tpm2_unseal(Tpm2Context
*c
,
5550 uint32_t hash_pcr_mask
,
5552 const struct iovec
*pubkey
,
5553 uint32_t pubkey_pcr_mask
,
5554 JsonVariant
*signature
,
5556 const Tpm2PCRLockPolicy
*pcrlock_policy
,
5557 uint16_t primary_alg
,
5558 const struct iovec
*blob
,
5559 const struct iovec
*known_policy_hash
,
5560 const struct iovec
*srk
,
5561 struct iovec
*ret_secret
) {
5566 assert(iovec_is_set(blob
));
5567 assert(iovec_is_valid(known_policy_hash
));
5568 assert(iovec_is_valid(pubkey
));
5571 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
5572 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
5574 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
5575 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
5576 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
5577 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
5578 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
5579 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5580 * and use it to unlock the LUKS2 volume. */
5582 usec_t start
= now(CLOCK_MONOTONIC
);
5584 TPM2B_PUBLIC
public;
5585 TPM2B_PRIVATE
private;
5586 TPM2B_ENCRYPTED_SECRET seed
= {};
5587 r
= tpm2_unmarshal_blob(blob
->iov_base
, blob
->iov_len
, &public, &private, &seed
);
5589 return log_debug_errno(r
, "Could not extract parts from blob: %m");
5591 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
5592 * so we need to handle that legacy situation. */
5593 if (pcr_bank
== UINT16_MAX
) {
5594 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
5599 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
5600 if (iovec_is_set(srk
)) {
5601 r
= tpm2_deserialize(c
, srk
->iov_base
, srk
->iov_len
, &primary_handle
);
5604 } else if (primary_alg
!= 0) {
5605 TPM2B_PUBLIC
template = {
5606 .size
= sizeof(TPMT_PUBLIC
),
5608 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5610 return log_debug_errno(r
, "Could not get legacy template: %m");
5612 r
= tpm2_create_primary(
5614 /* session= */ NULL
,
5616 /* sensitive= */ NULL
,
5617 /* ret_public= */ NULL
,
5622 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5623 "No SRK or primary alg provided.");
5625 if (seed
.size
> 0) {
5626 /* This is a calculated (or duplicated) sealed object, and must be imported. */
5627 _cleanup_free_ TPM2B_PRIVATE
*imported_private
= NULL
;
5630 /* session= */ NULL
,
5634 /* encryption_key= */ NULL
,
5635 /* symmetric= */ NULL
,
5640 private = *imported_private
;
5643 log_debug("Loading HMAC key into TPM.");
5646 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
5647 * gives you back a different key, the session initiation will fail. In the
5648 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
5649 * provides protections.
5651 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
5652 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
5656 TPM2B_PUBLIC pubkey_tpm2b
;
5657 _cleanup_(iovec_done
) struct iovec fp
= {};
5658 if (iovec_is_set(pubkey
)) {
5659 r
= tpm2_tpm2b_public_from_pem(pubkey
->iov_base
, pubkey
->iov_len
, &pubkey_tpm2b
);
5661 return log_debug_errno(r
, "Could not create TPMT_PUBLIC: %m");
5663 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
.iov_base
, &fp
.iov_len
);
5665 return log_debug_errno(r
, "Could not get key fingerprint: %m");
5669 * if a pin is set for the seal object, use it to bind the session
5670 * key to that object. This prevents active bus interposers from
5671 * faking a TPM and seeing the unsealed value. An active interposer
5672 * could fake a TPM, satisfying the encrypted session, and just
5673 * forward everything to the *real* TPM.
5675 r
= tpm2_set_auth(c
, hmac_key
, pin
);
5679 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
5680 for (unsigned i
= RETRY_UNSEAL_MAX
;; i
--) {
5681 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5682 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
5686 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*policy_session
= NULL
;
5687 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
5688 r
= tpm2_make_policy_session(
5696 r
= tpm2_build_sealing_policy(
5701 iovec_is_set(pubkey
) ? &pubkey_tpm2b
: NULL
,
5702 fp
.iov_base
, fp
.iov_len
,
5711 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
5712 * wait until the TPM2 tells us to go away. */
5713 if (iovec_is_set(known_policy_hash
) && memcmp_nn(policy_digest
->buffer
,
5714 policy_digest
->size
,
5715 known_policy_hash
->iov_base
,
5716 known_policy_hash
->iov_len
) != 0) {
5718 if (iovec_is_set(pubkey
) &&
5719 pubkey_tpm2b
.publicArea
.type
== TPM2_ALG_RSA
&&
5720 pubkey_tpm2b
.publicArea
.parameters
.rsaDetail
.exponent
== TPM2_RSA_DEFAULT_EXPONENT
) {
5721 /* Due to bug #30546, if using RSA pubkey with the default exponent, we may
5722 * need to set the exponent to the TPM special-case value of 0 and retry. */
5723 log_debug("Policy hash mismatch, retrying with RSA pubkey exponent set to 0.");
5724 pubkey_tpm2b
.publicArea
.parameters
.rsaDetail
.exponent
= 0;
5728 return log_debug_errno(SYNTHETIC_ERRNO(EPERM
),
5729 "Current policy digest does not match stored policy digest, cancelling "
5730 "TPM2 authentication attempt.");
5733 log_debug("Unsealing HMAC key.");
5735 rc
= sym_Esys_Unseal(
5737 hmac_key
->esys_handle
,
5738 policy_session
->esys_handle
,
5739 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
5742 if (rc
== TSS2_RC_SUCCESS
)
5744 if (rc
!= TPM2_RC_PCR_CHANGED
|| i
== 0)
5745 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5746 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc
));
5747 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i
);
5750 _cleanup_(iovec_done_erase
) struct iovec secret
= {};
5751 secret
.iov_base
= memdup(unsealed
->buffer
, unsealed
->size
);
5752 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
5753 if (!secret
.iov_base
)
5754 return log_oom_debug();
5755 secret
.iov_len
= unsealed
->size
;
5758 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5760 *ret_secret
= TAKE_STRUCT(secret
);
5765 static TPM2_HANDLE
generate_random_nv_index(void) {
5766 return TPM2_NV_INDEX_FIRST
+ (TPM2_HANDLE
) random_u64_range(TPM2_NV_INDEX_LAST
- TPM2_NV_INDEX_FIRST
+ 1);
5769 int tpm2_define_policy_nv_index(
5771 const Tpm2Handle
*session
,
5772 TPM2_HANDLE requested_nv_index
,
5773 const TPM2B_DIGEST
*write_policy
,
5775 const TPM2B_AUTH
*auth
,
5776 TPM2_HANDLE
*ret_nv_index
,
5777 Tpm2Handle
**ret_nv_handle
,
5778 TPM2B_NV_PUBLIC
*ret_nv_public
) {
5780 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*new_handle
= NULL
;
5785 assert(pin
|| auth
);
5787 /* Allocates an nvindex to store a policy for use in PolicyAuthorizeNV in. This is where pcrlock then
5788 * stores its predicted PCR policies in. If 'requested_nv_index' will try to allocate the specified
5789 * nvindex, otherwise will find a free one, and use that. */
5791 r
= tpm2_handle_new(c
, &new_handle
);
5795 new_handle
->flush
= false; /* This is a persistent NV index, don't flush hence */
5797 TPM2B_AUTH _auth
= {};
5798 CLEANUP_ERASE(_auth
);
5801 r
= tpm2_auth_value_from_pin(TPM2_ALG_SHA256
, pin
, &_auth
);
5808 for (unsigned try = 0; try < 25U; try++) {
5809 TPM2_HANDLE nv_index
;
5811 if (requested_nv_index
!= 0)
5812 nv_index
= requested_nv_index
;
5814 nv_index
= generate_random_nv_index();
5816 TPM2B_NV_PUBLIC public_info
= {
5817 .size
= sizeof_field(TPM2B_NV_PUBLIC
, nvPublic
),
5819 .nvIndex
= nv_index
,
5820 .nameAlg
= TPM2_ALG_SHA256
,
5821 .attributes
= TPM2_NT_ORDINARY
| TPMA_NV_WRITEALL
| TPMA_NV_POLICYWRITE
| TPMA_NV_OWNERREAD
,
5822 .dataSize
= offsetof(TPMT_HA
, digest
) + tpm2_hash_alg_to_size(TPM2_ALG_SHA256
),
5827 public_info
.nvPublic
.authPolicy
= *write_policy
;
5829 rc
= sym_Esys_NV_DefineSpace(
5831 /* authHandle= */ ESYS_TR_RH_OWNER
,
5832 /* shandle1= */ session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
5833 /* shandle2= */ ESYS_TR_NONE
,
5834 /* shandle3= */ ESYS_TR_NONE
,
5837 &new_handle
->esys_handle
);
5839 if (rc
== TSS2_RC_SUCCESS
) {
5840 log_debug("NV Index 0x%" PRIx32
" successfully allocated.", nv_index
);
5843 *ret_nv_index
= nv_index
;
5846 *ret_nv_handle
= TAKE_PTR(new_handle
);
5849 *ret_nv_public
= public_info
;
5853 if (rc
!= TPM2_RC_NV_DEFINED
)
5854 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5855 "Failed to allocate NV index: %s", sym_Tss2_RC_Decode(rc
));
5857 if (requested_nv_index
!= 0) {
5858 assert(nv_index
== requested_nv_index
);
5859 return log_debug_errno(SYNTHETIC_ERRNO(EEXIST
),
5860 "Requested NV index 0x%" PRIx32
" already taken.", requested_nv_index
);
5863 log_debug("NV index 0x%" PRIu32
" already taken, trying another one (%u tries left)", nv_index
, try);
5866 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5867 "Too many attempts trying to allocate NV index: %s", sym_Tss2_RC_Decode(rc
));
5870 int tpm2_write_policy_nv_index(
5872 const Tpm2Handle
*policy_session
,
5873 TPM2_HANDLE nv_index
,
5874 const Tpm2Handle
*nv_handle
,
5875 const TPM2B_DIGEST
*policy_digest
) {
5880 assert(policy_session
);
5882 assert(policy_digest
);
5884 if (policy_digest
->size
!= tpm2_hash_alg_to_size(TPM2_ALG_SHA256
))
5885 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Policy to store in NV index has wrong size.");
5888 .hashAlg
= TPM2_ALG_SHA256
,
5890 assert(policy_digest
->size
<= sizeof_field(TPMT_HA
, digest
));
5891 memcpy_safe(&ha
.digest
, policy_digest
->buffer
, policy_digest
->size
);
5893 TPM2B_MAX_NV_BUFFER buffer
= {};
5895 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, buffer
.buffer
, sizeof(buffer
.buffer
), &written
);
5896 if (rc
!= TSS2_RC_SUCCESS
)
5897 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5898 "Failed to marshal policy digest.");
5900 buffer
.size
= written
;
5902 rc
= sym_Esys_NV_Write(
5904 /* authHandle= */ nv_handle
->esys_handle
,
5905 /* nvIndex= */ nv_handle
->esys_handle
,
5906 /* shandle1= */ policy_session
->esys_handle
,
5907 /* shandle2= */ ESYS_TR_NONE
,
5908 /* shandle3= */ ESYS_TR_NONE
,
5911 if (rc
!= TSS2_RC_SUCCESS
)
5912 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5913 "Failed to write NV index: %s", sym_Tss2_RC_Decode(rc
));
5915 if (DEBUG_LOGGING
) {
5916 _cleanup_free_
char *h
= NULL
;
5917 h
= hexmem(policy_digest
->buffer
, policy_digest
->size
);
5918 log_debug("Written policy digest %s to NV index 0x%x", strnull(h
), nv_index
);
5924 int tpm2_undefine_policy_nv_index(
5926 const Tpm2Handle
*session
,
5927 TPM2_HANDLE nv_index
,
5928 const Tpm2Handle
*nv_handle
) {
5935 rc
= sym_Esys_NV_UndefineSpace(
5937 /* authHandle= */ ESYS_TR_RH_OWNER
,
5938 /* nvIndex= */ nv_handle
->esys_handle
,
5939 /* shandle1= */ session
? session
->esys_handle
: ESYS_TR_NONE
,
5940 /* shandle2= */ ESYS_TR_NONE
,
5941 /* shandle3= */ ESYS_TR_NONE
);
5942 if (rc
!= TSS2_RC_SUCCESS
)
5943 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5944 "Failed to undefine NV index: %s", sym_Tss2_RC_Decode(rc
));
5946 log_debug("Undefined NV index 0x%x", nv_index
);
5952 const struct iovec
*data
,
5953 const Tpm2Handle
*primary_handle
,
5954 const Tpm2Handle
*encryption_session
,
5955 const TPM2B_DIGEST
*policy
,
5956 struct iovec
*ret_public
,
5957 struct iovec
*ret_private
) {
5963 assert(primary_handle
);
5965 /* This is a generic version of tpm2_seal(), that doesn't imply any policy or any specific
5966 * combination of the two keypairs in their marshalling. tpm2_seal() is somewhat specific to the FDE
5967 * usecase. We probably should migrate tpm2_seal() to use tpm2_seal_data() eventually. */
5969 if (data
->iov_len
>= sizeof_field(TPMS_SENSITIVE_CREATE
, data
.buffer
))
5972 TPMT_PUBLIC hmac_template
= {
5973 .type
= TPM2_ALG_KEYEDHASH
,
5974 .nameAlg
= TPM2_ALG_SHA256
,
5975 .objectAttributes
= TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT
,
5976 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
5977 .unique
.keyedHash
.size
= data
->iov_len
,
5978 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
5981 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
5982 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
5985 CLEANUP_ERASE(hmac_sensitive
);
5987 memcpy_safe(hmac_sensitive
.data
.buffer
, data
->iov_base
, data
->iov_len
);
5989 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
5990 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
5991 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
5995 _cleanup_(iovec_done
) struct iovec public_blob
= {}, private_blob
= {};
5997 r
= tpm2_marshal_private(private, &private_blob
.iov_base
, &private_blob
.iov_len
);
6001 r
= tpm2_marshal_public(public, &public_blob
.iov_base
, &public_blob
.iov_len
);
6006 *ret_public
= TAKE_STRUCT(public_blob
);
6008 *ret_private
= TAKE_STRUCT(private_blob
);
6013 int tpm2_unseal_data(
6015 const struct iovec
*public_blob
,
6016 const struct iovec
*private_blob
,
6017 const Tpm2Handle
*primary_handle
,
6018 const Tpm2Handle
*policy_session
,
6019 const Tpm2Handle
*encryption_session
,
6020 struct iovec
*ret_data
) {
6026 assert(public_blob
);
6027 assert(private_blob
);
6028 assert(primary_handle
);
6030 TPM2B_PUBLIC
public;
6031 r
= tpm2_unmarshal_public(public_blob
->iov_base
, public_blob
->iov_len
, &public);
6035 TPM2B_PRIVATE
private;
6036 r
= tpm2_unmarshal_private(private_blob
->iov_base
, private_blob
->iov_len
, &private);
6040 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*what
= NULL
;
6041 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &what
);
6045 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
6046 rc
= sym_Esys_Unseal(
6049 policy_session
? policy_session
->esys_handle
: ESYS_TR_NONE
,
6050 encryption_session
? encryption_session
->esys_handle
: ESYS_TR_NONE
,
6053 if (rc
== TPM2_RC_PCR_CHANGED
)
6054 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE
),
6055 "PCR changed while unsealing.");
6056 if (rc
!= TSS2_RC_SUCCESS
)
6057 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
6058 "Failed to unseal data: %s", sym_Tss2_RC_Decode(rc
));
6060 _cleanup_(iovec_done
) struct iovec d
= {};
6061 d
= IOVEC_MAKE(memdup(unsealed
->buffer
, unsealed
->size
), unsealed
->size
);
6063 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
6066 return log_oom_debug();
6068 *ret_data
= TAKE_STRUCT(d
);
6071 #endif /* HAVE_TPM2 */
6073 int tpm2_list_devices(void) {
6075 _cleanup_(table_unrefp
) Table
*t
= NULL
;
6076 _cleanup_closedir_
DIR *d
= NULL
;
6081 return log_error_errno(r
, "TPM2 support is not installed.");
6083 t
= table_new("path", "device", "driver");
6087 d
= opendir("/sys/class/tpmrm");
6089 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
6090 if (errno
!= ENOENT
)
6094 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
6097 de
= readdir_no_dot(d
);
6101 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
6105 r
= readlink_malloc(device_path
, &device
);
6107 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
6109 driver_path
= path_join(device_path
, "driver");
6113 r
= readlink_malloc(driver_path
, &driver
);
6115 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
6118 node
= path_join("/dev", de
->d_name
);
6125 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
6126 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
6128 return table_log_add_error(r
);
6132 if (table_isempty(t
)) {
6133 log_info("No suitable TPM2 devices found.");
6137 r
= table_print(t
, stdout
);
6139 return log_error_errno(r
, "Failed to show device table: %m");
6143 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
6144 "TPM2 not supported on this build.");
6148 int tpm2_find_device_auto(char **ret
) {
6150 _cleanup_closedir_
DIR *d
= NULL
;
6155 return log_debug_errno(r
, "TPM2 support is not installed.");
6157 d
= opendir("/sys/class/tpmrm");
6159 log_debug_errno(errno
, "Failed to open /sys/class/tpmrm: %m");
6160 if (errno
!= ENOENT
)
6163 _cleanup_free_
char *node
= NULL
;
6168 de
= readdir_no_dot(d
);
6173 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
6174 "More than one TPM2 (tpmrm) device found.");
6176 node
= path_join("/dev", de
->d_name
);
6178 return log_oom_debug();
6182 *ret
= TAKE_PTR(node
);
6187 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
6189 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
6190 "TPM2 not supported on this build.");
6195 static const char* tpm2_userspace_event_type_table
[_TPM2_USERSPACE_EVENT_TYPE_MAX
] = {
6196 [TPM2_EVENT_PHASE
] = "phase",
6197 [TPM2_EVENT_FILESYSTEM
] = "filesystem",
6198 [TPM2_EVENT_VOLUME_KEY
] = "volume-key",
6199 [TPM2_EVENT_MACHINE_ID
] = "machine-id",
6202 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type
, Tpm2UserspaceEventType
);
6204 const char *tpm2_userspace_log_path(void) {
6205 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
6208 const char *tpm2_firmware_log_path(void) {
6209 return secure_getenv("SYSTEMD_MEASURE_LOG_FIRMWARE") ?: "/sys/kernel/security/tpm0/binary_bios_measurements";
6213 static int tpm2_userspace_log_open(void) {
6214 _cleanup_close_
int fd
= -EBADF
;
6219 e
= tpm2_userspace_log_path();
6220 (void) mkdir_parents(e
, 0755);
6222 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
6223 * because we use BSD file locking on it, and if anyone but root can access the file they can also
6224 * lock it, which we want to avoid. */
6225 fd
= open(e
, O_CREAT
|O_WRONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
, 0600);
6227 return log_debug_errno(errno
, "Failed to open TPM log file '%s' for writing, ignoring: %m", e
);
6229 if (flock(fd
, LOCK_EX
) < 0)
6230 return log_debug_errno(errno
, "Failed to lock TPM log file '%s', ignoring: %m", e
);
6232 if (fstat(fd
, &st
) < 0)
6233 return log_debug_errno(errno
, "Failed to fstat TPM log file '%s', ignoring: %m", e
);
6235 r
= stat_verify_regular(&st
);
6237 return log_debug_errno(r
, "TPM log file '%s' is not regular, ignoring: %m", e
);
6239 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
6240 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
6241 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
6242 * our assumed backend fs) doesn't know user xattrs. */
6243 if (st
.st_mode
& S_ISVTX
)
6244 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE
), "TPM log file '%s' aborted, ignoring.", e
);
6246 if (fchmod(fd
, 0600 | S_ISVTX
) < 0)
6247 return log_debug_errno(errno
, "Failed to chmod() TPM log file '%s', ignoring: %m", e
);
6252 static int tpm2_userspace_log(
6255 const TPML_DIGEST_VALUES
*values
,
6256 Tpm2UserspaceEventType event_type
,
6257 const char *description
) {
6259 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *array
= NULL
;
6260 _cleanup_free_
char *f
= NULL
;
6265 assert(values
->count
> 0);
6267 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
6268 * Format – the JSON flavour –
6269 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
6270 * ways from it, specifically:
6272 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
6273 * through the whole logs (include firmware logs) before knowing what the next value is we should
6274 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
6275 * it in when it uses the data.
6277 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
6278 * JSON array would mean that for each appending we'd have to read the whole log file fully into
6279 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
6280 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
6282 * It should be possible to convert this format in a relatively straight-forward way into the
6283 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
6284 * determined from the full dataset.
6286 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
6287 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
6288 * timestamp which can be used to order this measurement against possibly other measurements
6289 * independently done by other subsystems on the system.
6292 if (fd
< 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
6295 for (size_t i
= 0; i
< values
->count
; i
++) {
6296 const EVP_MD
*implementation
;
6299 assert_se(a
= tpm2_hash_alg_to_string(values
->digests
[i
].hashAlg
));
6300 assert_se(implementation
= EVP_get_digestbyname(a
));
6302 r
= json_variant_append_arrayb(
6303 &array
, JSON_BUILD_OBJECT(
6304 JSON_BUILD_PAIR_STRING("hashAlg", a
),
6305 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values
->digests
[i
].digest
, EVP_MD_size(implementation
)))));
6307 return log_debug_errno(r
, "Failed to append digest object to JSON array: %m");
6312 r
= sd_id128_get_boot(&boot_id
);
6314 return log_debug_errno(r
, "Failed to acquire boot ID: %m");
6316 r
= json_build(&v
, JSON_BUILD_OBJECT(
6317 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index
)),
6318 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array
)),
6319 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
6320 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
6321 JSON_BUILD_PAIR_CONDITION(description
, "string", JSON_BUILD_STRING(description
)),
6322 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id
)),
6323 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME
))),
6324 JSON_BUILD_PAIR_CONDITION(event_type
>= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type
)))))));
6326 return log_debug_errno(r
, "Failed to build log record JSON: %m");
6328 r
= json_variant_format(v
, JSON_FORMAT_SEQ
, &f
);
6330 return log_debug_errno(r
, "Failed to format JSON: %m");
6332 if (lseek(fd
, 0, SEEK_END
) < 0)
6333 return log_debug_errno(errno
, "Failed to seek to end of JSON log: %m");
6335 r
= loop_write(fd
, f
, SIZE_MAX
);
6337 return log_debug_errno(r
, "Failed to write JSON data to log: %m");
6340 return log_debug_errno(errno
, "Failed to sync JSON data: %m");
6342 /* Unset S_ISVTX again */
6343 if (fchmod(fd
, 0600) < 0)
6344 return log_debug_errno(errno
, "Failed to chmod() TPM log file, ignoring: %m");
6348 return log_debug_errno(r
, "Failed to sync JSON log: %m");
6354 int tpm2_extend_bytes(
6362 Tpm2UserspaceEventType event_type
,
6363 const char *description
) {
6366 _cleanup_close_
int log_fd
= -EBADF
;
6367 TPML_DIGEST_VALUES values
= {};
6371 assert(data
|| data_size
== 0);
6372 assert(secret
|| secret_size
== 0);
6374 if (data_size
== SIZE_MAX
)
6375 data_size
= strlen(data
);
6376 if (secret_size
== SIZE_MAX
)
6377 secret_size
= strlen(secret
);
6379 if (pcr_index
>= TPM2_PCRS_MAX
)
6380 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Can't measure into unsupported PCR %u, refusing.", pcr_index
);
6382 if (strv_isempty(banks
))
6385 STRV_FOREACH(bank
, banks
) {
6386 const EVP_MD
*implementation
;
6389 assert_se(implementation
= EVP_get_digestbyname(*bank
));
6391 if (values
.count
>= ELEMENTSOF(values
.digests
))
6392 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
6394 if ((size_t) EVP_MD_size(implementation
) > sizeof(values
.digests
[values
.count
].digest
))
6395 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Hash result too large for TPM2.");
6397 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
6399 return log_debug_errno(id
, "Can't map hash name to TPM2.");
6401 values
.digests
[values
.count
].hashAlg
= id
;
6403 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
6404 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
6405 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
6406 * secret for other purposes, maybe because it needs a shorter secret derived from it for
6407 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
6408 * private non-secret string instead. */
6409 if (secret_size
> 0) {
6410 if (!HMAC(implementation
, secret
, secret_size
, data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
))
6411 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to calculate HMAC of data to measure.");
6412 } else if (EVP_Digest(data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
, implementation
, NULL
) != 1)
6413 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to hash data to measure.");
6418 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
6419 * and our measurement and change either */
6420 log_fd
= tpm2_userspace_log_open();
6422 rc
= sym_Esys_PCR_Extend(
6424 ESYS_TR_PCR0
+ pcr_index
,
6429 if (rc
!= TSS2_RC_SUCCESS
)
6430 return log_debug_errno(
6431 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
6432 "Failed to measure into PCR %u: %s",
6434 sym_Tss2_RC_Decode(rc
));
6436 /* Now, write what we just extended to the log, too. */
6437 (void) tpm2_userspace_log(log_fd
, pcr_index
, &values
, event_type
, description
);
6440 #else /* HAVE_OPENSSL */
6441 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
6445 const uint16_t tpm2_hash_algorithms
[] = {
6453 assert_cc(ELEMENTSOF(tpm2_hash_algorithms
) == TPM2_N_HASH_ALGORITHMS
+ 1);
6455 static size_t tpm2_hash_algorithm_index(uint16_t algorithm
) {
6456 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++)
6457 if (tpm2_hash_algorithms
[i
] == algorithm
)
6463 TPM2B_DIGEST
*tpm2_pcr_prediction_result_get_hash(Tpm2PCRPredictionResult
*result
, uint16_t alg
) {
6468 alg_idx
= tpm2_hash_algorithm_index(alg
);
6469 if (alg_idx
== SIZE_MAX
) /* Algorithm not known? */
6472 if (result
->hash
[alg_idx
].size
<= 0) /* No hash value for this algorithm? */
6475 return result
->hash
+ alg_idx
;
6478 void tpm2_pcr_prediction_done(Tpm2PCRPrediction
*p
) {
6481 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++)
6482 ordered_set_free(p
->results
[pcr
]);
6485 static void tpm2_pcr_prediction_result_hash_func(const Tpm2PCRPredictionResult
*banks
, struct siphash
*state
) {
6488 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++)
6489 siphash24_compress_safe(banks
->hash
[i
].buffer
, banks
->hash
[i
].size
, state
);
6492 static int tpm2_pcr_prediction_result_compare_func(const Tpm2PCRPredictionResult
*a
, const Tpm2PCRPredictionResult
*b
) {
6498 for (size_t i
= 0; i
< TPM2_N_HASH_ALGORITHMS
; i
++) {
6499 r
= memcmp_nn(a
->hash
[i
].buffer
, a
->hash
[i
].size
,
6500 b
->hash
[i
].buffer
, b
->hash
[i
].size
);
6508 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
6509 tpm2_pcr_prediction_result_hash_ops
,
6510 Tpm2PCRPredictionResult
,
6511 tpm2_pcr_prediction_result_hash_func
,
6512 tpm2_pcr_prediction_result_compare_func
,
6513 Tpm2PCRPredictionResult
,
6516 static Tpm2PCRPredictionResult
*find_prediction_result_by_algorithm(OrderedSet
*set
, Tpm2PCRPredictionResult
*result
, size_t alg_idx
) {
6517 Tpm2PCRPredictionResult
*f
;
6520 assert(alg_idx
!= SIZE_MAX
);
6522 f
= ordered_set_get(set
, result
); /* Full match? */
6526 /* If this doesn't match full, then see if there an entry that at least matches by the relevant
6527 * algorithm (we are fine if predictions are "incomplete" in some algorithms) */
6529 ORDERED_SET_FOREACH(f
, set
)
6530 if (memcmp_nn(result
->hash
[alg_idx
].buffer
, result
->hash
[alg_idx
].size
,
6531 f
->hash
[alg_idx
].buffer
, f
->hash
[alg_idx
].size
) == 0)
6537 bool tpm2_pcr_prediction_equal(
6538 Tpm2PCRPrediction
*a
,
6539 Tpm2PCRPrediction
*b
,
6540 uint16_t algorithm
) {
6547 if (a
->pcrs
!= b
->pcrs
)
6550 size_t alg_idx
= tpm2_hash_algorithm_index(algorithm
);
6551 if (alg_idx
== SIZE_MAX
)
6554 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6555 Tpm2PCRPredictionResult
*banks
;
6557 ORDERED_SET_FOREACH(banks
, a
->results
[pcr
])
6558 if (!find_prediction_result_by_algorithm(b
->results
[pcr
], banks
, alg_idx
))
6561 ORDERED_SET_FOREACH(banks
, b
->results
[pcr
])
6562 if (!find_prediction_result_by_algorithm(a
->results
[pcr
], banks
, alg_idx
))
6569 int tpm2_pcr_prediction_to_json(
6570 const Tpm2PCRPrediction
*prediction
,
6572 JsonVariant
**ret
) {
6574 _cleanup_(json_variant_unrefp
) JsonVariant
*aj
= NULL
;
6580 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6581 _cleanup_(json_variant_unrefp
) JsonVariant
*vj
= NULL
;
6582 Tpm2PCRPredictionResult
*banks
;
6584 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6587 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6589 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6593 r
= json_variant_append_arrayb(
6595 JSON_BUILD_HEX(hash
->buffer
, hash
->size
));
6597 return log_error_errno(r
, "Failed to append hash variant to JSON array: %m");
6603 r
= json_variant_append_arrayb(
6606 JSON_BUILD_PAIR_INTEGER("pcr", pcr
),
6607 JSON_BUILD_PAIR_VARIANT("values", vj
)));
6609 return log_error_errno(r
, "Failed to append PCR variants to JSON array: %m");
6613 r
= json_variant_new_array(&aj
, NULL
, 0);
6618 *ret
= TAKE_PTR(aj
);
6622 int tpm2_pcr_prediction_from_json(
6623 Tpm2PCRPrediction
*prediction
,
6631 size_t alg_index
= tpm2_hash_algorithm_index(algorithm
);
6632 assert(alg_index
< TPM2_N_HASH_ALGORITHMS
);
6634 if (!json_variant_is_array(aj
))
6635 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR variant array is not an array.");
6638 JSON_VARIANT_ARRAY_FOREACH(pcr
, aj
) {
6639 JsonVariant
*nr
, *values
;
6641 nr
= json_variant_by_key(pcr
, "pcr");
6643 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks PCR index field");
6645 if (!json_variant_is_unsigned(nr
) ||
6646 json_variant_unsigned(nr
) >= TPM2_PCRS_MAX
)
6647 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry PCR index is not an integer in the range 0…23");
6649 values
= json_variant_by_key(pcr
, "values");
6651 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks values field");
6653 if (!json_variant_is_array(values
))
6654 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry values field is not an array");
6656 prediction
->pcrs
|= UINT32_C(1) << json_variant_unsigned(nr
);
6659 JSON_VARIANT_ARRAY_FOREACH(v
, values
) {
6660 _cleanup_free_
void *buffer
= NULL
;
6663 r
= json_variant_unhex(v
, &buffer
, &size
);
6665 return log_error_errno(r
, "Failed to decode PCR policy array hash value");
6668 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is zero.");
6670 if (size
> sizeof_field(TPM2B_DIGEST
, buffer
))
6671 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is too large.");
6673 _cleanup_free_ Tpm2PCRPredictionResult
*banks
= new0(Tpm2PCRPredictionResult
, 1);
6677 memcpy(banks
->hash
[alg_index
].buffer
, buffer
, size
);
6678 banks
->hash
[alg_index
].size
= size
;
6680 r
= ordered_set_ensure_put(prediction
->results
+ json_variant_unsigned(nr
), &tpm2_pcr_prediction_result_hash_ops
, banks
);
6681 if (r
== -EEXIST
) /* Let's allow duplicates */
6684 return log_error_errno(r
, "Failed to insert result into set: %m");
6693 int tpm2_calculate_policy_super_pcr(
6694 Tpm2PCRPrediction
*prediction
,
6696 TPM2B_DIGEST
*pcr_policy
) {
6700 assert_se(prediction
);
6701 assert_se(pcr_policy
);
6703 /* Start with a zero policy if not specified otherwise. */
6704 TPM2B_DIGEST super_pcr_policy_digest
= *pcr_policy
;
6706 /* First we look for all PCRs that have exactly one allowed hash value, and generate a single PolicyPCR policy from them */
6707 _cleanup_free_ Tpm2PCRValue
*single_values
= NULL
;
6708 size_t n_single_values
= 0;
6709 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6710 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6713 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6716 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6718 Tpm2PCRPredictionResult
*banks
= ASSERT_PTR(ordered_set_first(prediction
->results
[pcr
]));
6720 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6724 if (!GREEDY_REALLOC(single_values
, n_single_values
+ 1))
6727 single_values
[n_single_values
++] = TPM2_PCR_VALUE_MAKE(pcr
, algorithm
, *hash
);
6730 if (n_single_values
> 0) {
6731 /* Evolve policy based on the expected PCR value for what we found. */
6732 r
= tpm2_calculate_policy_pcr(
6735 &super_pcr_policy_digest
);
6740 /* Now deal with the PCRs for which we have variants, i.e. more than one allowed values */
6741 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6742 _cleanup_free_ TPM2B_DIGEST
*pcr_policy_digest_variants
= NULL
;
6743 size_t n_pcr_policy_digest_variants
= 0;
6744 Tpm2PCRPredictionResult
*banks
;
6746 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6749 if (ordered_set_size(prediction
->results
[pcr
]) <= 1) /* We only care for PCRs with 2 or more variants in this loop */
6752 if (ordered_set_size(prediction
->results
[pcr
]) > 8)
6753 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "PCR policies with more than 8 alternatives per PCR are currently not supported.");
6755 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6756 /* Start from the super PCR policy from the previous PCR we looked at so far. */
6757 TPM2B_DIGEST pcr_policy_digest
= super_pcr_policy_digest
;
6759 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6763 /* Evolve it based on the expected PCR value for this PCR */
6764 r
= tpm2_calculate_policy_pcr(
6765 &TPM2_PCR_VALUE_MAKE(
6769 /* n_pcr_values= */ 1,
6770 &pcr_policy_digest
);
6774 /* Store away this new variant */
6775 if (!GREEDY_REALLOC(pcr_policy_digest_variants
, n_pcr_policy_digest_variants
+ 1))
6778 pcr_policy_digest_variants
[n_pcr_policy_digest_variants
++] = pcr_policy_digest
;
6780 log_debug("Calculated PCR policy variant %zu for PCR %" PRIu32
, n_pcr_policy_digest_variants
, pcr
);
6783 assert_se(n_pcr_policy_digest_variants
>= 2);
6784 assert_se(n_pcr_policy_digest_variants
<= 8);
6786 /* Now combine all our variant into one OR policy */
6787 r
= tpm2_calculate_policy_or(
6788 pcr_policy_digest_variants
,
6789 n_pcr_policy_digest_variants
,
6790 &super_pcr_policy_digest
);
6794 log_debug("Combined %zu variants in OR policy.", n_pcr_policy_digest_variants
);
6797 *pcr_policy
= super_pcr_policy_digest
;
6801 int tpm2_policy_super_pcr(
6803 const Tpm2Handle
*session
,
6804 const Tpm2PCRPrediction
*prediction
,
6805 uint16_t algorithm
) {
6811 assert_se(prediction
);
6813 TPM2B_DIGEST previous_policy_digest
= TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
);
6815 uint32_t single_value_pcrs
= 0;
6817 /* Look for all PCRs that have only a singled allowed hash value, and synthesize a single PolicyPCR policy item for them */
6818 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6819 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6822 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6825 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6827 single_value_pcrs
|= UINT32_C(1) << pcr
;
6830 if (single_value_pcrs
!= 0) {
6831 TPML_PCR_SELECTION pcr_selection
;
6832 tpm2_tpml_pcr_selection_from_mask(single_value_pcrs
, algorithm
, &pcr_selection
);
6834 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6835 r
= tpm2_policy_pcr(
6839 ¤t_policy_digest
);
6843 previous_policy_digest
= *current_policy_digest
;
6846 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6849 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6852 n_branches
= ordered_set_size(prediction
->results
[pcr
]);
6853 if (n_branches
< 1 || n_branches
> 8)
6854 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "Number of variants per PCR not in range 1…8");
6856 if (n_branches
== 1) /* Single choice PCRs are already covered by the loop above */
6859 log_debug("Submitting PCR/OR policy for PCR %" PRIu32
, pcr
);
6861 TPML_PCR_SELECTION pcr_selection
;
6862 tpm2_tpml_pcr_selection_from_mask(UINT32_C(1) << pcr
, algorithm
, &pcr_selection
);
6864 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6865 r
= tpm2_policy_pcr(
6869 ¤t_policy_digest
);
6873 _cleanup_free_ TPM2B_DIGEST
*branches
= NULL
;
6874 branches
= new0(TPM2B_DIGEST
, n_branches
);
6878 Tpm2PCRPredictionResult
*banks
;
6880 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6881 TPM2B_DIGEST pcr_policy_digest
= previous_policy_digest
;
6883 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6887 /* Evolve it based on the expected PCR value for this PCR */
6888 r
= tpm2_calculate_policy_pcr(
6889 &TPM2_PCR_VALUE_MAKE(
6893 /* n_pcr_values= */ 1,
6894 &pcr_policy_digest
);
6898 branches
[i
++] = pcr_policy_digest
;
6901 assert_se(i
== n_branches
);
6903 current_policy_digest
= mfree(current_policy_digest
);
6909 ¤t_policy_digest
);
6913 previous_policy_digest
= *current_policy_digest
;
6919 void tpm2_pcrlock_policy_done(Tpm2PCRLockPolicy
*data
) {
6922 data
->prediction_json
= json_variant_unref(data
->prediction_json
);
6923 tpm2_pcr_prediction_done(&data
->prediction
);
6924 iovec_done(&data
->nv_handle
);
6925 iovec_done(&data
->nv_public
);
6926 iovec_done(&data
->srk_handle
);
6927 iovec_done(&data
->pin_public
);
6928 iovec_done(&data
->pin_private
);
6931 static int json_dispatch_tpm2_algorithm(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
6932 uint16_t *algorithm
= ASSERT_PTR(userdata
);
6935 r
= tpm2_hash_alg_from_string(json_variant_string(variant
));
6936 if (r
< 0 || tpm2_hash_algorithm_index(r
) == SIZE_MAX
)
6937 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid hash algorithm: %s", json_variant_string(variant
));
6943 int tpm2_pcrlock_search_file(const char *path
, FILE **ret_file
, char **ret_path
) {
6944 static const char search
[] =
6946 "/var/lib/systemd\0";
6951 path
= "pcrlock.json";
6953 r
= search_and_fopen_nulstr(path
, ret_file
? "re" : NULL
, NULL
, search
, ret_file
, ret_path
);
6955 return log_debug_errno(r
, "Failed to find TPM2 pcrlock policy file '%s': %m", path
);
6960 int tpm2_pcrlock_policy_from_json(
6962 Tpm2PCRLockPolicy
*ret_policy
) {
6964 /* We use a type check of _JSON_VARIANT_TYPE_INVALID for the integer fields to allow
6965 * json_dispatch_uint32() to parse strings as integers to work around the integer type weakness of
6967 JsonDispatch policy_dispatch
[] = {
6968 { "pcrBank", JSON_VARIANT_STRING
, json_dispatch_tpm2_algorithm
, offsetof(Tpm2PCRLockPolicy
, algorithm
), JSON_MANDATORY
},
6969 { "pcrValues", JSON_VARIANT_ARRAY
, json_dispatch_variant
, offsetof(Tpm2PCRLockPolicy
, prediction_json
), JSON_MANDATORY
},
6970 { "nvIndex", _JSON_VARIANT_TYPE_INVALID
, json_dispatch_uint32
, offsetof(Tpm2PCRLockPolicy
, nv_index
), JSON_MANDATORY
},
6971 { "nvHandle", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, nv_handle
), JSON_MANDATORY
},
6972 { "nvPublic", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, nv_public
), JSON_MANDATORY
},
6973 { "srkHandle", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, srk_handle
), JSON_MANDATORY
},
6974 { "pinPublic", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, pin_public
), JSON_MANDATORY
},
6975 { "pinPrivate", JSON_VARIANT_STRING
, json_dispatch_unbase64_iovec
, offsetof(Tpm2PCRLockPolicy
, pin_private
), JSON_MANDATORY
},
6979 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy policy
= {};
6985 r
= json_dispatch(v
, policy_dispatch
, JSON_LOG
, &policy
);
6989 r
= tpm2_pcr_prediction_from_json(&policy
.prediction
, policy
.algorithm
, policy
.prediction_json
);
6993 *ret_policy
= TAKE_STRUCT(policy
);
6997 int tpm2_pcrlock_policy_load(
6999 Tpm2PCRLockPolicy
*ret_policy
) {
7001 _cleanup_free_
char *discovered_path
= NULL
;
7002 _cleanup_fclose_
FILE *f
= NULL
;
7005 r
= tpm2_pcrlock_search_file(path
, &f
, &discovered_path
);
7007 *ret_policy
= (Tpm2PCRLockPolicy
) {};
7011 return log_error_errno(r
, "Failed to load TPM2 pcrlock policy file: %m");
7013 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
7014 r
= json_parse_file(
7019 /* ret_line= */ NULL
,
7020 /* ret_column= */ NULL
);
7022 return log_error_errno(r
, "Failed to parse existing pcrlock policy file '%s': %m", discovered_path
);
7024 return tpm2_pcrlock_policy_from_json(v
, ret_policy
);
7027 static int pcrlock_policy_load_credential(
7029 const struct iovec
*data
,
7030 Tpm2PCRLockPolicy
*ret
) {
7032 _cleanup_free_
char *c
= NULL
;
7041 ascii_strlower(c
); /* Lowercase, to match what we did at encryption time */
7043 _cleanup_(iovec_done
) struct iovec decoded
= {};
7044 r
= decrypt_credential_and_warn(
7046 now(CLOCK_REALTIME
),
7047 /* tpm2_device= */ NULL
,
7048 /* tpm2_signature_path= */ NULL
,
7051 CREDENTIAL_ALLOW_NULL
,
7056 if (memchr(decoded
.iov_base
, 0, decoded
.iov_len
))
7057 return log_error_errno(r
, "Credential '%s' contains embedded NUL byte, refusing.", name
);
7059 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
7060 r
= json_parse(decoded
.iov_base
,
7063 /* ret_line= */ NULL
,
7064 /* ret_column= */ NULL
);
7066 return log_error_errno(r
, "Failed to parse pcrlock policy: %m");
7068 r
= tpm2_pcrlock_policy_from_json(v
, ret
);
7075 int tpm2_pcrlock_policy_from_credentials(
7076 const struct iovec
*srk
,
7077 const struct iovec
*nv
,
7078 Tpm2PCRLockPolicy
*ret
) {
7080 _cleanup_close_
int dfd
= -EBADF
;
7083 /* During boot we'll not have access to the pcrlock.json file in /var/. In order to support
7084 * pcrlock-bound root file systems we'll store a copy of the JSON data, wrapped in an (plaintext)
7085 * credential in the ESP or XBOOTLDR partition. There might be multiple of those however (because of
7086 * multi-boot), hence we use the SRK and NV data from the LUKS2 header as search key, and parse all
7087 * such JSON policies until we find a matching one. */
7089 const char *cp
= secure_getenv("SYSTEMD_ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY") ?: ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
;
7091 dfd
= open(cp
, O_CLOEXEC
|O_DIRECTORY
);
7093 if (errno
== ENOENT
) {
7094 log_debug("No encrypted system credentials passed.");
7098 return log_error_errno(errno
, "Failed to open system credentials directory.");
7101 _cleanup_free_ DirectoryEntries
*de
= NULL
;
7102 r
= readdir_all(dfd
, RECURSE_DIR_IGNORE_DOT
, &de
);
7104 return log_error_errno(r
, "Failed to enumerate system credentials: %m");
7106 FOREACH_ARRAY(i
, de
->entries
, de
->n_entries
) {
7107 _cleanup_(iovec_done
) struct iovec data
= {};
7108 struct dirent
*d
= *i
;
7110 if (!startswith_no_case(d
->d_name
, "pcrlock.")) /* VFAT is case-insensitive, hence don't be too strict here */
7113 r
= read_full_file_full(
7115 /* offset= */ UINT64_MAX
,
7116 /* size= */ CREDENTIAL_ENCRYPTED_SIZE_MAX
,
7117 READ_FULL_FILE_UNBASE64
|READ_FULL_FILE_FAIL_WHEN_LARGER
,
7118 /* bind_name= */ NULL
,
7119 (char**) &data
.iov_base
,
7124 log_warning_errno(r
, "Failed to read credentials file %s/%s, skipping: %m", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
7128 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy loaded_policy
= {};
7129 r
= pcrlock_policy_load_credential(
7134 log_warning_errno(r
, "Loading of pcrlock policy from credential '%s/%s' failed, skipping.", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
7138 if ((!srk
|| iovec_memcmp(srk
, &loaded_policy
.srk_handle
) == 0) &&
7139 (!nv
|| iovec_memcmp(nv
, &loaded_policy
.nv_handle
) == 0)) {
7140 *ret
= TAKE_STRUCT(loaded_policy
);
7145 log_info("No pcrlock policy found among system credentials.");
7146 *ret
= (Tpm2PCRLockPolicy
) {};
7150 int tpm2_load_public_key_file(const char *path
, TPM2B_PUBLIC
*ret
) {
7151 _cleanup_free_
char *device_key_buffer
= NULL
;
7152 TPM2B_PUBLIC device_key_public
= {};
7153 size_t device_key_buffer_size
;
7162 return log_debug_errno(r
, "TPM2 support not installed: %m");
7164 r
= read_full_file(path
, &device_key_buffer
, &device_key_buffer_size
);
7166 return log_error_errno(r
, "Failed to read device key from file '%s': %m", path
);
7169 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(
7170 (uint8_t*) device_key_buffer
,
7171 device_key_buffer_size
,
7173 &device_key_public
);
7174 if (rc
!= TSS2_RC_SUCCESS
)
7175 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
7176 "Could not unmarshal public key from file.");
7178 assert(offset
<= device_key_buffer_size
);
7179 if (offset
!= device_key_buffer_size
)
7180 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
7181 "Found %zu bytes of trailing garbage in public key file.",
7182 device_key_buffer_size
- offset
);
7184 *ret
= device_key_public
;
7188 int tpm2_hmac_key_from_pin(Tpm2Context
*c
, const Tpm2Handle
*session
, const TPM2B_AUTH
*pin
, Tpm2Handle
**ret
) {
7195 log_debug("Converting PIN into TPM2 HMAC-SHA256 object.");
7197 /* Load the PIN (which we have stored in the "auth" TPM2B_AUTH) into the TPM as an HMAC key so that
7198 * we can use it in a TPM2_PolicySigned() to write to the nvindex. For that we'll prep a pair of
7199 * TPM2B_PUBLIC and TPM2B_SENSITIVE that defines an HMAC-SHA256 keyed hash function, and initialize
7200 * it based on on the provided PIN data. */
7202 TPM2B_PUBLIC auth_hmac_public
= {
7204 .type
= TPM2_ALG_KEYEDHASH
,
7205 .nameAlg
= TPM2_ALG_SHA256
,
7206 .objectAttributes
= TPMA_OBJECT_SIGN_ENCRYPT
,
7207 .parameters
.keyedHashDetail
.scheme
= {
7208 .scheme
= TPM2_ALG_HMAC
,
7209 .details
.hmac
.hashAlg
= TPM2_ALG_SHA256
,
7211 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
7215 TPM2B_SENSITIVE auth_hmac_private
= {
7217 .sensitiveType
= TPM2_ALG_KEYEDHASH
,
7218 .sensitive
.bits
.size
= pin
->size
,
7219 .seedValue
.size
= SHA256_DIGEST_SIZE
,
7223 /* Copy in the key data */
7224 memcpy_safe(auth_hmac_private
.sensitiveArea
.sensitive
.bits
.buffer
, pin
->buffer
, pin
->size
);
7226 /* NB: We initialize the seed of the TPMT_SENSITIVE structure to all zeroes, since we want a stable
7227 * "name" of the PIN object */
7229 /* Now calculate the "unique" field for the public area, based on the sensitive data, according to
7230 * the algorithm in the TPM2 spec, part 1, Section 27.5.3.2 */
7231 struct iovec sensitive_data
[] = {
7232 IOVEC_MAKE(auth_hmac_private
.sensitiveArea
.seedValue
.buffer
, auth_hmac_private
.sensitiveArea
.seedValue
.size
),
7233 IOVEC_MAKE(auth_hmac_private
.sensitiveArea
.sensitive
.bits
.buffer
, auth_hmac_private
.sensitiveArea
.sensitive
.bits
.size
),
7235 r
= tpm2_digest_many(
7236 auth_hmac_public
.publicArea
.nameAlg
,
7237 &auth_hmac_public
.publicArea
.unique
.keyedHash
,
7239 ELEMENTSOF(sensitive_data
),
7240 /* extend= */ false);
7244 /* And now load the public/private parts into the TPM and get a handle back */
7245 r
= tpm2_load_external(
7252 return log_error_errno(r
, "Failed to load PIN into TPM2: %m");
7258 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
7259 _cleanup_free_
char *s
= NULL
;
7261 FOREACH_PCR_IN_MASK(n
, mask
)
7262 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
7271 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
7272 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
7277 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
7278 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
7280 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
7283 r
= json_variant_new_integer(&e
, i
);
7287 r
= json_variant_append_array(&a
, e
);
7293 return json_variant_new_array(ret
, NULL
, 0);
7299 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
7303 if (!json_variant_is_array(v
))
7304 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
7306 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
7309 if (!json_variant_is_unsigned(e
))
7310 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
7312 u
= json_variant_unsigned(e
);
7313 if (u
>= TPM2_PCRS_MAX
)
7314 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR number out of range: %" PRIu64
, u
);
7316 mask
|= UINT32_C(1) << u
;
7325 int tpm2_make_luks2_json(
7327 uint32_t hash_pcr_mask
,
7329 const struct iovec
*pubkey
,
7330 uint32_t pubkey_pcr_mask
,
7331 uint16_t primary_alg
,
7332 const struct iovec
*blob
,
7333 const struct iovec
*policy_hash
,
7334 const struct iovec
*salt
,
7335 const struct iovec
*srk
,
7336 const struct iovec
*pcrlock_nv
,
7338 JsonVariant
**ret
) {
7340 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
7341 _cleanup_free_
char *keyslot_as_string
= NULL
;
7344 assert(iovec_is_valid(pubkey
));
7345 assert(iovec_is_valid(blob
));
7346 assert(iovec_is_valid(policy_hash
));
7348 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
7351 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
7355 if (pubkey_pcr_mask
!= 0) {
7356 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
7361 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
7362 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
7363 * object should use "_" rather than "-" in field names. */
7367 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
7368 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string
))),
7369 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_IOVEC_BASE64(blob
)),
7370 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj
)),
7371 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank
), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank
))),
7372 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg
), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg
))),
7373 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_IOVEC_HEX(policy_hash
)),
7374 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags
& TPM2_FLAGS_USE_PIN
)),
7375 JSON_BUILD_PAIR("tpm2_pcrlock", JSON_BUILD_BOOLEAN(flags
& TPM2_FLAGS_USE_PCRLOCK
)),
7376 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj
)),
7377 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey", JSON_BUILD_IOVEC_BASE64(pubkey
)),
7378 JSON_BUILD_PAIR_CONDITION(iovec_is_set(salt
), "tpm2_salt", JSON_BUILD_IOVEC_BASE64(salt
)),
7379 JSON_BUILD_PAIR_CONDITION(iovec_is_set(srk
), "tpm2_srk", JSON_BUILD_IOVEC_BASE64(srk
)),
7380 JSON_BUILD_PAIR_CONDITION(iovec_is_set(pcrlock_nv
), "tpm2_pcrlock_nv", JSON_BUILD_IOVEC_BASE64(pcrlock_nv
))));
7390 int tpm2_parse_luks2_json(
7393 uint32_t *ret_hash_pcr_mask
,
7394 uint16_t *ret_pcr_bank
,
7395 struct iovec
*ret_pubkey
,
7396 uint32_t *ret_pubkey_pcr_mask
,
7397 uint16_t *ret_primary_alg
,
7398 struct iovec
*ret_blob
,
7399 struct iovec
*ret_policy_hash
,
7400 struct iovec
*ret_salt
,
7401 struct iovec
*ret_srk
,
7402 struct iovec
*ret_pcrlock_nv
,
7403 TPM2Flags
*ret_flags
) {
7405 _cleanup_(iovec_done
) struct iovec blob
= {}, policy_hash
= {}, pubkey
= {}, salt
= {}, srk
= {}, pcrlock_nv
= {};
7406 uint32_t hash_pcr_mask
= 0, pubkey_pcr_mask
= 0;
7407 uint16_t primary_alg
= TPM2_ALG_ECC
; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
7408 uint16_t pcr_bank
= UINT16_MAX
; /* default: pick automatically */
7409 int r
, keyslot
= -1;
7410 TPM2Flags flags
= 0;
7416 keyslot
= cryptsetup_get_keyslot_from_token(v
);
7418 /* Return a recognizable error when parsing this field, so that callers can handle parsing
7419 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
7421 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
7426 w
= json_variant_by_key(v
, "tpm2-pcrs");
7428 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
7430 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
7432 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
7434 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
7436 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
7438 /* The PCR bank field is optional */
7440 if (!json_variant_is_string(w
))
7441 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
7443 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
7445 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
7450 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
7451 * the algorithm was hardcoded to ECC. */
7452 w
= json_variant_by_key(v
, "tpm2-primary-alg");
7454 /* The primary key algorithm is optional */
7456 if (!json_variant_is_string(w
))
7457 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
7459 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
7461 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
7466 w
= json_variant_by_key(v
, "tpm2-blob");
7468 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
7470 r
= json_variant_unbase64_iovec(w
, &blob
);
7472 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
7474 w
= json_variant_by_key(v
, "tpm2-policy-hash");
7476 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
7478 r
= json_variant_unhex_iovec(w
, &policy_hash
);
7480 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
7482 w
= json_variant_by_key(v
, "tpm2-pin");
7484 if (!json_variant_is_boolean(w
))
7485 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
7487 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
7490 w
= json_variant_by_key(v
, "tpm2_pcrlock");
7492 if (!json_variant_is_boolean(w
))
7493 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 pclock policy is not a boolean.");
7495 SET_FLAG(flags
, TPM2_FLAGS_USE_PCRLOCK
, json_variant_boolean(w
));
7498 w
= json_variant_by_key(v
, "tpm2_salt");
7500 r
= json_variant_unbase64_iovec(w
, &salt
);
7502 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
7505 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
7507 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
7512 w
= json_variant_by_key(v
, "tpm2_pubkey");
7514 r
= json_variant_unbase64_iovec(w
, &pubkey
);
7516 return log_debug_errno(r
, "Failed to decode PCR public key.");
7517 } else if (pubkey_pcr_mask
!= 0)
7518 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Public key PCR mask set, but not public key included in JSON data, refusing.");
7520 w
= json_variant_by_key(v
, "tpm2_srk");
7522 r
= json_variant_unbase64_iovec(w
, &srk
);
7524 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
7527 w
= json_variant_by_key(v
, "tpm2_pcrlock_nv");
7529 r
= json_variant_unbase64_iovec(w
, &pcrlock_nv
);
7531 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_pcrlock_nv' field.");
7535 *ret_keyslot
= keyslot
;
7536 if (ret_hash_pcr_mask
)
7537 *ret_hash_pcr_mask
= hash_pcr_mask
;
7539 *ret_pcr_bank
= pcr_bank
;
7541 *ret_pubkey
= TAKE_STRUCT(pubkey
);
7542 if (ret_pubkey_pcr_mask
)
7543 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
7544 if (ret_primary_alg
)
7545 *ret_primary_alg
= primary_alg
;
7547 *ret_blob
= TAKE_STRUCT(blob
);
7548 if (ret_policy_hash
)
7549 *ret_policy_hash
= TAKE_STRUCT(policy_hash
);
7551 *ret_salt
= TAKE_STRUCT(salt
);
7553 *ret_srk
= TAKE_STRUCT(srk
);
7555 *ret_pcrlock_nv
= TAKE_STRUCT(pcrlock_nv
);
7561 int tpm2_hash_alg_to_size(uint16_t alg
) {
7565 case TPM2_ALG_SHA256
:
7567 case TPM2_ALG_SHA384
:
7569 case TPM2_ALG_SHA512
:
7572 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
7576 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
7580 case TPM2_ALG_SHA256
:
7582 case TPM2_ALG_SHA384
:
7584 case TPM2_ALG_SHA512
:
7587 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
7592 int tpm2_hash_alg_from_string(const char *alg
) {
7593 if (strcaseeq_ptr(alg
, "sha1"))
7594 return TPM2_ALG_SHA1
;
7595 if (strcaseeq_ptr(alg
, "sha256"))
7596 return TPM2_ALG_SHA256
;
7597 if (strcaseeq_ptr(alg
, "sha384"))
7598 return TPM2_ALG_SHA384
;
7599 if (strcaseeq_ptr(alg
, "sha512"))
7600 return TPM2_ALG_SHA512
;
7601 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm name '%s'", alg
);
7604 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
7611 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
7616 int tpm2_asym_alg_from_string(const char *alg
) {
7617 if (strcaseeq_ptr(alg
, "ecc"))
7618 return TPM2_ALG_ECC
;
7619 if (strcaseeq_ptr(alg
, "rsa"))
7620 return TPM2_ALG_RSA
;
7621 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown asymmetric algorithm name '%s'", alg
);
7624 const char *tpm2_sym_alg_to_string(uint16_t alg
) {
7631 log_debug("Unknown symmetric algorithm id 0x%" PRIx16
, alg
);
7636 int tpm2_sym_alg_from_string(const char *alg
) {
7638 if (strcaseeq_ptr(alg
, "aes"))
7639 return TPM2_ALG_AES
;
7641 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric algorithm name '%s'", alg
);
7644 const char *tpm2_sym_mode_to_string(uint16_t mode
) {
7659 log_debug("Unknown symmetric mode id 0x%" PRIx16
, mode
);
7664 int tpm2_sym_mode_from_string(const char *mode
) {
7666 if (strcaseeq_ptr(mode
, "ctr"))
7667 return TPM2_ALG_CTR
;
7668 if (strcaseeq_ptr(mode
, "ofb"))
7669 return TPM2_ALG_OFB
;
7670 if (strcaseeq_ptr(mode
, "cbc"))
7671 return TPM2_ALG_CBC
;
7672 if (strcaseeq_ptr(mode
, "cfb"))
7673 return TPM2_ALG_CFB
;
7674 if (strcaseeq_ptr(mode
, "ecb"))
7675 return TPM2_ALG_ECB
;
7677 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric mode name '%s'", mode
);
7680 Tpm2Support
tpm2_support(void) {
7681 Tpm2Support support
= TPM2_SUPPORT_NONE
;
7684 if (detect_container() <= 0) {
7685 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
7686 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
7687 * let's assume containers never have a TPM, at least for now. */
7689 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
7692 log_debug_errno(r
, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
7693 } else if (r
== 0) /* populated! */
7694 support
|= TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_DRIVER
;
7696 /* If the directory exists but is empty, we know the subsystem is enabled but no
7697 * driver has been loaded yet. */
7698 support
|= TPM2_SUPPORT_SUBSYSTEM
;
7702 support
|= TPM2_SUPPORT_FIRMWARE
;
7705 support
|= TPM2_SUPPORT_SYSTEM
;
7709 support
|= TPM2_SUPPORT_LIBRARIES
;
7716 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
7717 TPMI_ALG_HASH default_hash
= 0;
7718 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
7720 default_hash
= v
->hash
;
7724 if (default_hash
!= 0)
7725 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
7727 v
->hash
= default_hash
;
7731 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
7732 * parse_*_argument() functions. */
7734 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
7736 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
7737 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
7738 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
7740 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
7741 * tpm2_parse_pcr_argument_append(). */
7742 int tpm2_parse_pcr_argument(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
7747 assert(ret_pcr_values
);
7748 assert(ret_n_pcr_values
);
7750 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
7751 size_t n_pcr_values
= 0;
7752 r
= tpm2_pcr_values_from_string(arg
, &pcr_values
, &n_pcr_values
);
7754 return log_error_errno(r
, "Could not parse PCR values from '%s': %m", arg
);
7756 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
7758 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
7760 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
7761 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
7763 *ret_pcr_values
= TAKE_PTR(pcr_values
);
7764 *ret_n_pcr_values
= n_pcr_values
;
7768 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7772 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
7773 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
7776 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
7777 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
7778 * algorithm check applied again (in case either the previous or current array had no default hash
7779 * algorithm), and then the resulting array is sorted and rechecked for validity. */
7780 int tpm2_parse_pcr_argument_append(const char *arg
, Tpm2PCRValue
**pcr_values
, size_t *n_pcr_values
) {
7786 assert(n_pcr_values
);
7788 _cleanup_free_ Tpm2PCRValue
*more_pcr_values
= NULL
;
7789 size_t n_more_pcr_values
;
7790 r
= tpm2_parse_pcr_argument(arg
, &more_pcr_values
, &n_more_pcr_values
);
7794 /* If we got previous values, append them. */
7795 if (*pcr_values
&& !GREEDY_REALLOC_APPEND(more_pcr_values
, n_more_pcr_values
, *pcr_values
, *n_pcr_values
))
7798 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values
, n_more_pcr_values
);
7800 tpm2_sort_pcr_values(more_pcr_values
, n_more_pcr_values
);
7802 if (!tpm2_pcr_values_valid(more_pcr_values
, n_more_pcr_values
))
7803 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
7805 SWAP_TWO(*pcr_values
, more_pcr_values
);
7806 *n_pcr_values
= n_more_pcr_values
;
7810 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7814 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
7815 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
7816 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
7817 * UINT32_MAX, and or-ing the mask otherwise. */
7818 int tpm2_parse_pcr_argument_to_mask(const char *arg
, uint32_t *ret_mask
) {
7820 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
7821 size_t n_pcr_values
;
7827 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
7831 if (n_pcr_values
== 0) {
7832 /* This retains the previous behavior of clearing the mask if the arg is empty */
7838 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
7840 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
7843 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
7846 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
7848 return log_error_errno(r
, "Could not get pcr values mask: %m");
7850 if (*ret_mask
== UINT32_MAX
)
7851 *ret_mask
= new_mask
;
7853 *ret_mask
|= new_mask
;
7857 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
7861 int tpm2_load_pcr_signature(const char *path
, JsonVariant
**ret
) {
7862 _cleanup_strv_free_
char **search
= NULL
;
7863 _cleanup_free_
char *discovered_path
= NULL
;
7864 _cleanup_fclose_
FILE *f
= NULL
;
7867 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
7868 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7870 search
= strv_new(CONF_PATHS("systemd"));
7872 return log_oom_debug();
7875 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
7876 * this case include /.extra/ in the search path, but only in this case, and if we run in the
7877 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
7879 path
= "tpm2-pcr-signature.json";
7882 if (strv_extend(&search
, "/.extra") < 0)
7883 return log_oom_debug();
7886 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
7888 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
7890 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
7892 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
7897 int tpm2_load_pcr_public_key(const char *path
, void **ret_pubkey
, size_t *ret_pubkey_size
) {
7898 _cleanup_free_
char *discovered_path
= NULL
;
7899 _cleanup_fclose_
FILE *f
= NULL
;
7902 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
7903 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7906 path
= "tpm2-pcr-public-key.pem";
7908 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
7910 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
7912 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
7914 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
7919 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
7922 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
7923 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
7924 * I found the wikipedia entry relevant and it contains links to
7926 * - https://en.wikipedia.org/wiki/PBKDF2
7927 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
7929 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
7933 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
7935 _cleanup_(erase_and_freep
) uint8_t *buffer
= NULL
;
7936 uint8_t u
[SHA256_DIGEST_SIZE
];
7938 /* To keep this simple, since derived KeyLen (dkLen in docs)
7939 * Is the same as the hash output, we don't need multiple
7940 * blocks. Part of the algorithm is to add the block count
7941 * in, but this can be hardcoded to 1.
7943 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
7946 assert (saltlen
> 0);
7947 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
7948 assert (passlen
> 0);
7951 * Build a buffer of salt + block_cnt and hmac_sha256 it we
7952 * do this as we don't have a context builder for HMAC_SHA256.
7954 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
7958 memcpy(buffer
, salt
, saltlen
);
7959 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
7961 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
7963 /* dk needs to be an unmodified u as u gets modified in the loop */
7964 memcpy(ret_key
, u
, SHA256_DIGEST_SIZE
);
7965 uint8_t *dk
= ret_key
;
7967 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
7968 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
7970 for (size_t j
=0; j
< sizeof(u
); j
++)
7977 static const char* const tpm2_pcr_index_table
[_TPM2_PCR_INDEX_MAX_DEFINED
] = {
7978 [TPM2_PCR_PLATFORM_CODE
] = "platform-code",
7979 [TPM2_PCR_PLATFORM_CONFIG
] = "platform-config",
7980 [TPM2_PCR_EXTERNAL_CODE
] = "external-code",
7981 [TPM2_PCR_EXTERNAL_CONFIG
] = "external-config",
7982 [TPM2_PCR_BOOT_LOADER_CODE
] = "boot-loader-code",
7983 [TPM2_PCR_BOOT_LOADER_CONFIG
] = "boot-loader-config",
7984 [TPM2_PCR_HOST_PLATFORM
] = "host-platform",
7985 [TPM2_PCR_SECURE_BOOT_POLICY
] = "secure-boot-policy",
7986 [TPM2_PCR_KERNEL_INITRD
] = "kernel-initrd",
7987 [TPM2_PCR_IMA
] = "ima",
7988 [TPM2_PCR_KERNEL_BOOT
] = "kernel-boot",
7989 [TPM2_PCR_KERNEL_CONFIG
] = "kernel-config",
7990 [TPM2_PCR_SYSEXTS
] = "sysexts",
7991 [TPM2_PCR_SHIM_POLICY
] = "shim-policy",
7992 [TPM2_PCR_SYSTEM_IDENTITY
] = "system-identity",
7993 [TPM2_PCR_DEBUG
] = "debug",
7994 [TPM2_PCR_APPLICATION_SUPPORT
] = "application-support",
7997 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index
, int, TPM2_PCRS_MAX
- 1);
7998 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index
, int);