1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "cryptsetup-util.h"
8 #include "dirent-util.h"
9 #include "dlfcn-util.h"
11 #include "extract-word.h"
14 #include "format-table.h"
16 #include "hexdecoct.h"
18 #include "initrd-util.h"
20 #include "lock-util.h"
22 #include "logarithm.h"
23 #include "memory-util.h"
25 #include "nulstr-util.h"
26 #include "parse-util.h"
27 #include "random-util.h"
29 #include "sort-util.h"
30 #include "stat-util.h"
31 #include "string-table.h"
32 #include "sync-util.h"
33 #include "time-util.h"
34 #include "tpm2-util.h"
38 static void *libtss2_esys_dl
= NULL
;
39 static void *libtss2_rc_dl
= NULL
;
40 static void *libtss2_mu_dl
= NULL
;
42 static TSS2_RC (*sym_Esys_Create
)(ESYS_CONTEXT
*esysContext
, ESYS_TR parentHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_SENSITIVE_CREATE
*inSensitive
, const TPM2B_PUBLIC
*inPublic
, const TPM2B_DATA
*outsideInfo
, const TPML_PCR_SELECTION
*creationPCR
, TPM2B_PRIVATE
**outPrivate
, TPM2B_PUBLIC
**outPublic
, TPM2B_CREATION_DATA
**creationData
, TPM2B_DIGEST
**creationHash
, TPMT_TK_CREATION
**creationTicket
) = NULL
;
43 static TSS2_RC (*sym_Esys_CreateLoaded
)(ESYS_CONTEXT
*esysContext
, ESYS_TR parentHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_SENSITIVE_CREATE
*inSensitive
, const TPM2B_TEMPLATE
*inPublic
, ESYS_TR
*objectHandle
, TPM2B_PRIVATE
**outPrivate
, TPM2B_PUBLIC
**outPublic
) = NULL
;
44 static TSS2_RC (*sym_Esys_CreatePrimary
)(ESYS_CONTEXT
*esysContext
, ESYS_TR primaryHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_SENSITIVE_CREATE
*inSensitive
, const TPM2B_PUBLIC
*inPublic
, const TPM2B_DATA
*outsideInfo
, const TPML_PCR_SELECTION
*creationPCR
, ESYS_TR
*objectHandle
, TPM2B_PUBLIC
**outPublic
, TPM2B_CREATION_DATA
**creationData
, TPM2B_DIGEST
**creationHash
, TPMT_TK_CREATION
**creationTicket
) = NULL
;
45 static TSS2_RC (*sym_Esys_EvictControl
)(ESYS_CONTEXT
*esysContext
, ESYS_TR auth
, ESYS_TR objectHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, TPMI_DH_PERSISTENT persistentHandle
, ESYS_TR
*newObjectHandle
) = NULL
;
46 static void (*sym_Esys_Finalize
)(ESYS_CONTEXT
**context
) = NULL
;
47 static TSS2_RC (*sym_Esys_FlushContext
)(ESYS_CONTEXT
*esysContext
, ESYS_TR flushHandle
) = NULL
;
48 static void (*sym_Esys_Free
)(void *ptr
) = NULL
;
49 static TSS2_RC (*sym_Esys_GetCapability
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, TPM2_CAP capability
, UINT32 property
, UINT32 propertyCount
, TPMI_YES_NO
*moreData
, TPMS_CAPABILITY_DATA
**capabilityData
) = NULL
;
50 static TSS2_RC (*sym_Esys_GetRandom
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, UINT16 bytesRequested
, TPM2B_DIGEST
**randomBytes
) = NULL
;
51 static TSS2_RC (*sym_Esys_Initialize
)(ESYS_CONTEXT
**esys_context
, TSS2_TCTI_CONTEXT
*tcti
, TSS2_ABI_VERSION
*abiVersion
) = NULL
;
52 static TSS2_RC (*sym_Esys_Load
)(ESYS_CONTEXT
*esysContext
, ESYS_TR parentHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_PRIVATE
*inPrivate
, const TPM2B_PUBLIC
*inPublic
, ESYS_TR
*objectHandle
) = NULL
;
53 static TSS2_RC (*sym_Esys_LoadExternal
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_SENSITIVE
*inPrivate
, const TPM2B_PUBLIC
*inPublic
, ESYS_TR hierarchy
, ESYS_TR
*objectHandle
) = NULL
;
54 static TSS2_RC (*sym_Esys_PCR_Extend
)(ESYS_CONTEXT
*esysContext
, ESYS_TR pcrHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPML_DIGEST_VALUES
*digests
) = NULL
;
55 static TSS2_RC (*sym_Esys_PCR_Read
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
,ESYS_TR shandle2
, ESYS_TR shandle3
, const TPML_PCR_SELECTION
*pcrSelectionIn
, UINT32
*pcrUpdateCounter
, TPML_PCR_SELECTION
**pcrSelectionOut
, TPML_DIGEST
**pcrValues
) = NULL
;
56 static TSS2_RC (*sym_Esys_PolicyAuthorize
)(ESYS_CONTEXT
*esysContext
, ESYS_TR policySession
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_DIGEST
*approvedPolicy
, const TPM2B_NONCE
*policyRef
, const TPM2B_NAME
*keySign
, const TPMT_TK_VERIFIED
*checkTicket
) = NULL
;
57 static TSS2_RC (*sym_Esys_PolicyAuthValue
)(ESYS_CONTEXT
*esysContext
, ESYS_TR policySession
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
) = NULL
;
58 static TSS2_RC (*sym_Esys_PolicyGetDigest
)(ESYS_CONTEXT
*esysContext
, ESYS_TR policySession
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, TPM2B_DIGEST
**policyDigest
) = NULL
;
59 static TSS2_RC (*sym_Esys_PolicyPCR
)(ESYS_CONTEXT
*esysContext
, ESYS_TR policySession
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_DIGEST
*pcrDigest
, const TPML_PCR_SELECTION
*pcrs
) = NULL
;
60 static TSS2_RC (*sym_Esys_ReadPublic
)(ESYS_CONTEXT
*esysContext
, ESYS_TR objectHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, TPM2B_PUBLIC
**outPublic
, TPM2B_NAME
**name
, TPM2B_NAME
**qualifiedName
) = NULL
;
61 static TSS2_RC (*sym_Esys_StartAuthSession
)(ESYS_CONTEXT
*esysContext
, ESYS_TR tpmKey
, ESYS_TR bind
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_NONCE
*nonceCaller
, TPM2_SE sessionType
, const TPMT_SYM_DEF
*symmetric
, TPMI_ALG_HASH authHash
, ESYS_TR
*sessionHandle
) = NULL
;
62 static TSS2_RC (*sym_Esys_Startup
)(ESYS_CONTEXT
*esysContext
, TPM2_SU startupType
) = NULL
;
63 static TSS2_RC (*sym_Esys_TestParms
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPMT_PUBLIC_PARMS
*parameters
) = NULL
;
64 static TSS2_RC (*sym_Esys_TR_Close
)(ESYS_CONTEXT
*esys_context
, ESYS_TR
*rsrc_handle
) = NULL
;
65 static TSS2_RC (*sym_Esys_TR_Deserialize
)(ESYS_CONTEXT
*esys_context
, uint8_t const *buffer
, size_t buffer_size
, ESYS_TR
*esys_handle
) = NULL
;
66 static TSS2_RC (*sym_Esys_TR_FromTPMPublic
)(ESYS_CONTEXT
*esysContext
, TPM2_HANDLE tpm_handle
, ESYS_TR optionalSession1
, ESYS_TR optionalSession2
, ESYS_TR optionalSession3
, ESYS_TR
*object
) = NULL
;
67 static TSS2_RC (*sym_Esys_TR_GetName
)(ESYS_CONTEXT
*esysContext
, ESYS_TR handle
, TPM2B_NAME
**name
) = NULL
;
68 static TSS2_RC (*sym_Esys_TR_GetTpmHandle
)(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, TPM2_HANDLE
*tpm_handle
) = NULL
;
69 static TSS2_RC (*sym_Esys_TR_Serialize
)(ESYS_CONTEXT
*esys_context
, ESYS_TR object
, uint8_t **buffer
, size_t *buffer_size
) = NULL
;
70 static TSS2_RC (*sym_Esys_TR_SetAuth
)(ESYS_CONTEXT
*esysContext
, ESYS_TR handle
, TPM2B_AUTH
const *authValue
) = NULL
;
71 static TSS2_RC (*sym_Esys_TRSess_GetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION
*flags
) = NULL
;
72 static TSS2_RC (*sym_Esys_TRSess_SetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION flags
, TPMA_SESSION mask
) = NULL
;
73 static TSS2_RC (*sym_Esys_Unseal
)(ESYS_CONTEXT
*esysContext
, ESYS_TR itemHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, TPM2B_SENSITIVE_DATA
**outData
) = NULL
;
74 static TSS2_RC (*sym_Esys_VerifySignature
)(ESYS_CONTEXT
*esysContext
, ESYS_TR keyHandle
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPM2B_DIGEST
*digest
, const TPMT_SIGNATURE
*signature
, TPMT_TK_VERIFIED
**validation
) = NULL
;
76 static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal
)(TPM2_CC src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
77 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal
)(TPM2B_PRIVATE
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
78 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PRIVATE
*dest
) = NULL
;
79 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal
)(TPM2B_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
80 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PUBLIC
*dest
) = NULL
;
81 static TSS2_RC (*sym_Tss2_MU_TPML_PCR_SELECTION_Marshal
)(TPML_PCR_SELECTION
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
82 static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal
)(TPMT_HA
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
83 static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal
)(TPMT_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
85 static const char* (*sym_Tss2_RC_Decode
)(TSS2_RC rc
) = NULL
;
87 int dlopen_tpm2(void) {
90 r
= dlopen_many_sym_or_warn(
91 &libtss2_esys_dl
, "libtss2-esys.so.0", LOG_DEBUG
,
92 DLSYM_ARG(Esys_Create
),
93 DLSYM_ARG(Esys_CreateLoaded
),
94 DLSYM_ARG(Esys_CreatePrimary
),
95 DLSYM_ARG(Esys_EvictControl
),
96 DLSYM_ARG(Esys_Finalize
),
97 DLSYM_ARG(Esys_FlushContext
),
99 DLSYM_ARG(Esys_GetCapability
),
100 DLSYM_ARG(Esys_GetRandom
),
101 DLSYM_ARG(Esys_Initialize
),
102 DLSYM_ARG(Esys_Load
),
103 DLSYM_ARG(Esys_LoadExternal
),
104 DLSYM_ARG(Esys_PCR_Extend
),
105 DLSYM_ARG(Esys_PCR_Read
),
106 DLSYM_ARG(Esys_PolicyAuthorize
),
107 DLSYM_ARG(Esys_PolicyAuthValue
),
108 DLSYM_ARG(Esys_PolicyGetDigest
),
109 DLSYM_ARG(Esys_PolicyPCR
),
110 DLSYM_ARG(Esys_ReadPublic
),
111 DLSYM_ARG(Esys_StartAuthSession
),
112 DLSYM_ARG(Esys_Startup
),
113 DLSYM_ARG(Esys_TestParms
),
114 DLSYM_ARG(Esys_TR_Close
),
115 DLSYM_ARG(Esys_TR_Deserialize
),
116 DLSYM_ARG(Esys_TR_FromTPMPublic
),
117 DLSYM_ARG(Esys_TR_GetName
),
118 DLSYM_ARG(Esys_TR_Serialize
),
119 DLSYM_ARG(Esys_TR_SetAuth
),
120 DLSYM_ARG(Esys_TRSess_GetAttributes
),
121 DLSYM_ARG(Esys_TRSess_SetAttributes
),
122 DLSYM_ARG(Esys_Unseal
),
123 DLSYM_ARG(Esys_VerifySignature
));
127 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
128 * version of 2.4.0 this sym can be moved up to the normal list above. */
129 r
= dlsym_many_or_warn(libtss2_esys_dl
, LOG_DEBUG
, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle
));
131 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
133 r
= dlopen_many_sym_or_warn(
134 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
135 DLSYM_ARG(Tss2_RC_Decode
));
139 return dlopen_many_sym_or_warn(
140 &libtss2_mu_dl
, "libtss2-mu.so.0", LOG_DEBUG
,
141 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal
),
142 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal
),
143 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal
),
144 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal
),
145 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal
),
146 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal
),
147 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal
),
148 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal
));
151 void Esys_Freep(void *p
) {
153 sym_Esys_Free(*(void**) p
);
156 /* Get a specific TPM capability (or capabilities).
158 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
159 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
160 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
161 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
163 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
164 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
165 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
166 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
167 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
168 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
169 * capability category may have more specific requirements than described here; see the spec for exact
171 static int tpm2_get_capability(
176 TPMU_CAPABILITIES
*ret_capability_data
) {
178 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
184 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
185 capability
, property
, count
);
187 rc
= sym_Esys_GetCapability(
197 if (rc
!= TSS2_RC_SUCCESS
)
198 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
199 "Failed to get TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
": %s",
200 capability
, property
, sym_Tss2_RC_Decode(rc
));
202 if (capabilities
->capability
!= capability
)
203 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
204 "TPM provided wrong capability: 0x%04" PRIx32
" instead of 0x%04" PRIx32
".",
205 capabilities
->capability
, capability
);
207 if (ret_capability_data
)
208 *ret_capability_data
= capabilities
->data
;
210 return more
== TPM2_YES
;
213 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
215 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
216 TPMU_CAPABILITIES capability
;
221 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
222 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
223 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
224 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
225 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
226 * changed while we are performing some operation, it's reasonable to assume it will break us even if
227 * we don't cache the algorithms, thus they should be "safe" to cache. */
228 TPM2_ALG_ID current_alg
= TPM2_ALG_FIRST
;
230 r
= tpm2_get_capability(
233 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
239 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
241 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
242 * there are no more. */
243 assert(algorithms
.count
> 0);
245 if (!GREEDY_REALLOC_APPEND(
246 c
->capability_algorithms
,
247 c
->n_capability_algorithms
,
248 algorithms
.algProperties
,
250 return log_oom_debug();
255 /* Set current_alg to alg id after last alg id the TPM provided */
256 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
259 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
260 * while running, but that would be crazy, so let's hope it is not possible. */
261 TPM2_CC current_cc
= TPM2_CC_FIRST
;
263 r
= tpm2_get_capability(
272 TPML_CCA commands
= capability
.command
;
274 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
275 * there are no more. */
276 assert(commands
.count
> 0);
278 if (!GREEDY_REALLOC_APPEND(
279 c
->capability_commands
,
280 c
->n_capability_commands
,
281 commands
.commandAttributes
,
283 return log_oom_debug();
288 /* Set current_cc to index after last cc the TPM provided */
289 current_cc
= TPMA_CC_TO_TPM2_CC(commands
.commandAttributes
[commands
.count
- 1]) + 1;
292 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
293 * while running, but that would be crazy, so let's hope it is not possible. */
294 TPM2_ECC_CURVE current_ecc_curve
= TPM2_ECC_NONE
;
296 r
= tpm2_get_capability(
305 TPML_ECC_CURVE ecc_curves
= capability
.eccCurves
;
307 /* ECC support isn't required */
308 if (ecc_curves
.count
== 0)
311 if (!GREEDY_REALLOC_APPEND(
312 c
->capability_ecc_curves
,
313 c
->n_capability_ecc_curves
,
314 ecc_curves
.eccCurves
,
316 return log_oom_debug();
321 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
322 current_ecc_curve
= ecc_curves
.eccCurves
[ecc_curves
.count
- 1] + 1;
325 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
326 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
327 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
328 * safely assume the TPM PCR allocation will not change while we are using it. */
329 r
= tpm2_get_capability(
338 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
339 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
340 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
341 * this command with the full PCR allocation and moreData will be NO." */
342 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
343 c
->capability_pcrs
= capability
.assignedPCR
;
348 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
349 * TPMA_ALGORITHM is provided, otherwise false. */
350 static bool tpm2_get_capability_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
, TPMA_ALGORITHM
*ret
) {
353 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
354 if (alg_prop
->alg
== alg
) {
356 *ret
= alg_prop
->algProperties
;
360 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
367 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
368 return tpm2_get_capability_alg(c
, alg
, NULL
);
371 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
372 * otherwise false. */
373 static bool tpm2_get_capability_command(Tpm2Context
*c
, TPM2_CC command
, TPMA_CC
*ret
) {
376 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
377 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
383 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
390 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
391 return tpm2_get_capability_command(c
, command
, NULL
);
394 /* Returns true if the TPM supports the ECC curve, otherwise false. */
395 bool tpm2_supports_ecc_curve(Tpm2Context
*c
, TPM2_ECC_CURVE ecc_curve
) {
398 FOREACH_ARRAY(curve
, c
->capability_ecc_curves
, c
->n_capability_ecc_curves
)
399 if (*curve
== ecc_curve
)
402 log_debug("TPM does not support ECC curve 0x%" PRIx16
".", ecc_curve
);
406 /* Query the TPM for populated handles.
408 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
409 * contain only populated handle addresses (which might not include the requested handle). The number of
410 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
411 * range (i.e. handle & 0xff000000).
413 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
414 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
415 static int tpm2_get_capability_handles(
419 TPM2_HANDLE
**ret_handles
,
420 size_t *ret_n_handles
) {
422 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
423 size_t n_handles
= 0;
424 TPM2_HANDLE current
= start
;
429 assert(ret_n_handles
);
431 max
= MIN(max
, UINT32_MAX
);
434 TPMU_CAPABILITIES capability
;
435 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
439 TPML_HANDLE handle_list
= capability
.handles
;
440 if (handle_list
.count
== 0)
443 assert(handle_list
.count
<= max
);
445 if (n_handles
> SIZE_MAX
- handle_list
.count
)
446 return log_oom_debug();
448 if (!GREEDY_REALLOC_APPEND(handles
, n_handles
, handle_list
.handle
, handle_list
.count
))
449 return log_oom_debug();
451 max
-= handle_list
.count
;
453 /* Update current to the handle index after the last handle in the list. */
454 current
= handles
[n_handles
- 1] + 1;
457 /* No more handles in this range. */
461 *ret_handles
= TAKE_PTR(handles
);
462 *ret_n_handles
= n_handles
;
467 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
468 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
470 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
471 static int tpm2_get_capability_handle(Tpm2Context
*c
, TPM2_HANDLE handle
) {
472 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
473 size_t n_handles
= 0;
476 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
480 return n_handles
== 0 ? false : handles
[0] == handle
;
483 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
484 bool tpm2_test_parms(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, const TPMU_PUBLIC_PARMS
*parms
) {
490 TPMT_PUBLIC_PARMS parameters
= {
492 .parameters
= *parms
,
495 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
496 if (rc
!= TSS2_RC_SUCCESS
)
497 /* The spec says if the parms are not supported the TPM returns "...the appropriate
498 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
499 * unmarshaling errors, instead of checking for them all here, let's just assume any error
500 * indicates unsupported parms, and log the specific error text. */
501 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc
));
503 return rc
== TSS2_RC_SUCCESS
;
506 static bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
510 return tpm2_test_parms(c
, public->type
, &public->parameters
);
513 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
517 TPMU_PUBLIC_PARMS parms
= {
518 .symDetail
.sym
= *parameters
,
521 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
524 static bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
528 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
529 * functionally identical. */
530 TPMT_SYM_DEF_OBJECT object
= {
531 .algorithm
= parameters
->algorithm
,
532 .keyBits
= parameters
->keyBits
,
533 .mode
= parameters
->mode
,
536 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
539 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
544 sym_Esys_Finalize(&c
->esys_context
);
546 c
->tcti_context
= mfree(c
->tcti_context
);
547 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
549 c
->capability_algorithms
= mfree(c
->capability_algorithms
);
550 c
->capability_commands
= mfree(c
->capability_commands
);
551 c
->capability_ecc_curves
= mfree(c
->capability_ecc_curves
);
556 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
558 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
559 .algorithm
= TPM2_ALG_AES
,
561 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
564 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
565 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
571 context
= new(Tpm2Context
, 1);
573 return log_oom_debug();
575 *context
= (Tpm2Context
) {
581 return log_debug_errno(r
, "TPM2 support not installed: %m");
584 device
= secure_getenv("SYSTEMD_TPM2_DEVICE");
586 /* Setting the env var to an empty string forces tpm2-tss' own device picking
587 * logic to be used. */
588 device
= empty_to_null(device
);
590 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
591 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
592 * might be used and we really don't want that, since it is a system service and that creates
593 * various ordering issues/deadlocks during early boot. */
594 device
= "device:/dev/tpmrm0";
598 const char *param
, *driver
, *fn
;
599 const TSS2_TCTI_INFO
* info
;
600 TSS2_TCTI_INFO_FUNC func
;
603 param
= strchr(device
, ':');
605 /* Syntax #1: Pair of driver string and arbitrary parameter */
606 driver
= strndupa_safe(device
, param
- device
);
608 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
611 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
612 /* Syntax #2: TPM device node */
616 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
618 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
620 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
622 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
623 if (!filename_is_valid(fn
))
624 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name '%s' not valid, refusing.", driver
);
626 context
->tcti_dl
= dlopen(fn
, RTLD_NOW
);
627 if (!context
->tcti_dl
)
628 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to load %s: %s", fn
, dlerror());
630 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
632 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
633 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
638 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
640 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
642 rc
= info
->init(NULL
, &sz
, NULL
);
643 if (rc
!= TPM2_RC_SUCCESS
)
644 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
645 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
647 context
->tcti_context
= malloc0(sz
);
648 if (!context
->tcti_context
)
649 return log_oom_debug();
651 rc
= info
->init(context
->tcti_context
, &sz
, param
);
652 if (rc
!= TPM2_RC_SUCCESS
)
653 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
654 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
657 rc
= sym_Esys_Initialize(&context
->esys_context
, context
->tcti_context
, NULL
);
658 if (rc
!= TSS2_RC_SUCCESS
)
659 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
660 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc
));
662 rc
= sym_Esys_Startup(context
->esys_context
, TPM2_SU_CLEAR
);
663 if (rc
== TPM2_RC_INITIALIZE
)
664 log_debug("TPM already started up.");
665 else if (rc
== TSS2_RC_SUCCESS
)
666 log_debug("TPM successfully started up.");
668 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
669 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
671 r
= tpm2_cache_capabilities(context
);
673 return log_debug_errno(r
, "Failed to cache TPM capabilities: %m");
675 /* We require AES and CFB support for session encryption. */
676 if (!tpm2_supports_alg(context
, TPM2_ALG_AES
))
677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES.");
679 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
680 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support CFB.");
682 if (!tpm2_supports_tpmt_sym_def(context
, &SESSION_TEMPLATE_SYM_AES_128_CFB
))
683 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES-128-CFB.");
685 *ret_context
= TAKE_PTR(context
);
690 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
693 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
696 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
697 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
698 * as removing its corresponding handle from the actual TPM. */
700 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
702 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
703 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
704 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
705 * directly affects us; for example the src/test/test-tpm2.c test function
706 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
707 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
708 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
709 * references will be cleaned up when we free our ESYS_CONTEXT.
711 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
712 rc
= TSS2_RC_SUCCESS
; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
713 if (rc
!= TSS2_RC_SUCCESS
)
714 /* We ignore failures here (besides debug logging), since this is called in error paths,
715 * where we cannot do anything about failures anymore. And when it is called in successful
716 * codepaths by this time we already did what we wanted to do, and got the results we wanted
717 * so there's no reason to make this fail more loudly than necessary. */
718 log_debug("Failed to %s TPM handle, ignoring: %s", flush
? "flush" : "close", sym_Tss2_RC_Decode(rc
));
721 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
725 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
727 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
729 return mfree(handle
);
732 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
733 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
737 handle
= new(Tpm2Handle
, 1);
739 return log_oom_debug();
741 *handle
= (Tpm2Handle
) {
742 .tpm2_context
= tpm2_context_ref(context
),
743 .esys_handle
= ESYS_TR_NONE
,
747 *ret_handle
= TAKE_PTR(handle
);
752 static int tpm2_read_public(
754 const Tpm2Handle
*session
,
755 const Tpm2Handle
*handle
,
756 TPM2B_PUBLIC
**ret_public
,
757 TPM2B_NAME
**ret_name
,
758 TPM2B_NAME
**ret_qname
) {
765 rc
= sym_Esys_ReadPublic(
768 session
? session
->esys_handle
: ESYS_TR_NONE
,
774 if (rc
!= TSS2_RC_SUCCESS
)
775 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
776 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
781 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
782 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
783 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
784 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
786 int tpm2_index_to_handle(
789 const Tpm2Handle
*session
,
790 TPM2B_PUBLIC
**ret_public
,
791 TPM2B_NAME
**ret_name
,
792 TPM2B_NAME
**ret_qname
,
793 Tpm2Handle
**ret_handle
) {
800 /* Only allow persistent, transient, or NV index handle types. */
801 switch (TPM2_HANDLE_TYPE(index
)) {
802 case TPM2_HT_PERSISTENT
:
803 case TPM2_HT_NV_INDEX
:
804 case TPM2_HT_TRANSIENT
:
807 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
808 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
809 "Invalid handle 0x%08" PRIx32
" (in PCR range).", index
);
810 case TPM2_HT_HMAC_SESSION
:
811 case TPM2_HT_POLICY_SESSION
:
812 /* Session indexes are only used internally by tpm2-tss (or lower code) */
813 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
814 "Invalid handle 0x%08" PRIx32
" (in session range).", index
);
815 case TPM2_HT_PERMANENT
:
816 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
817 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
818 "Invalid handle 0x%08" PRIx32
" (in permanent range).", index
);
820 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
821 "Invalid handle 0x%08" PRIx32
" (in unknown range).", index
);
824 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
825 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
826 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
827 if (TPM2_HANDLE_TYPE(index
) != TPM2_HT_TRANSIENT
) { // FIXME: once kernel bug is fixed, check transient handles too
828 r
= tpm2_get_capability_handle(c
, index
);
832 log_debug("TPM handle 0x%08" PRIx32
" not populated.", index
);
845 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
846 r
= tpm2_handle_new(c
, &handle
);
850 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
851 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
852 handle
->flush
= false;
854 rc
= sym_Esys_TR_FromTPMPublic(
857 session
? session
->esys_handle
: ESYS_TR_NONE
,
860 &handle
->esys_handle
);
861 if (rc
!= TSS2_RC_SUCCESS
)
862 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
863 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
865 if (ret_public
|| ret_name
|| ret_qname
) {
866 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
872 *ret_handle
= TAKE_PTR(handle
);
877 /* Get the handle index for the provided Tpm2Handle. */
878 int tpm2_index_from_handle(Tpm2Context
*c
, const Tpm2Handle
*handle
, TPM2_HANDLE
*ret_index
) {
885 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
886 * version of 2.4.0 this check can be removed. */
887 if (!sym_Esys_TR_GetTpmHandle
)
888 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
889 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
891 rc
= sym_Esys_TR_GetTpmHandle(c
->esys_context
, handle
->esys_handle
, ret_index
);
892 if (rc
!= TSS2_RC_SUCCESS
)
893 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
894 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc
));
899 /* Copy an object in the TPM at a transient handle to a persistent handle.
901 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
902 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
903 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
906 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
907 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
908 * at the requested persistent handle index (or the first available if none was requested).
910 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
911 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
912 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
913 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
914 * memory for persistent storage. The persistent handle is only provided when returning 1. */
915 static int tpm2_persist_handle(
917 const Tpm2Handle
*transient_handle
,
918 const Tpm2Handle
*session
,
919 TPMI_DH_PERSISTENT persistent_handle_index
,
920 Tpm2Handle
**ret_persistent_handle
) {
922 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
923 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
924 TPMI_DH_PERSISTENT first
= UINT32_C(0x81000000), last
= UINT32_C(0x81ffffff);
929 assert(transient_handle
);
931 /* If persistent handle index specified, only try that. */
932 if (persistent_handle_index
!= 0) {
933 if (TPM2_HANDLE_TYPE(persistent_handle_index
) != TPM2_HT_PERSISTENT
)
934 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
935 "Handle not in persistent range: 0x%x", persistent_handle_index
);
937 first
= last
= persistent_handle_index
;
940 for (TPMI_DH_PERSISTENT requested
= first
; requested
<= last
; requested
++) {
941 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*persistent_handle
= NULL
;
942 r
= tpm2_handle_new(c
, &persistent_handle
);
946 /* Since this is a persistent handle, don't flush it. */
947 persistent_handle
->flush
= false;
949 rc
= sym_Esys_EvictControl(
952 transient_handle
->esys_handle
,
953 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
957 &persistent_handle
->esys_handle
);
958 if (rc
== TSS2_RC_SUCCESS
) {
959 if (ret_persistent_handle
)
960 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
964 if (rc
!= TPM2_RC_NV_DEFINED
)
965 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
966 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc
));
969 if (ret_persistent_handle
)
970 *ret_persistent_handle
= NULL
;
975 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
977 static int tpm2_credit_random(Tpm2Context
*c
) {
978 size_t rps
, done
= 0;
985 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
986 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
987 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
990 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH
, F_OK
) < 0) {
992 log_debug_errno(errno
, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH
"' exists, ignoring: %m");
994 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
995 return 0; /* Already done */
998 t
= now(CLOCK_MONOTONIC
);
1000 for (rps
= random_pool_size(); rps
> 0;) {
1001 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
1003 rc
= sym_Esys_GetRandom(
1008 MIN(rps
, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1010 if (rc
!= TSS2_RC_SUCCESS
)
1011 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1012 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc
));
1014 if (buffer
->size
== 0)
1015 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1016 "Zero-sized entropy returned from TPM.");
1018 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
1020 return log_debug_errno(r
, "Failed wo write entropy to kernel: %m");
1022 done
+= buffer
->size
;
1023 rps
= LESS_BY(rps
, buffer
->size
);
1026 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
1028 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
1030 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
1035 /* Get one of the legacy primary key templates.
1037 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1038 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1039 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1040 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1041 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1042 /* Do not modify. */
1043 static const TPMT_PUBLIC legacy_ecc
= {
1044 .type
= TPM2_ALG_ECC
,
1045 .nameAlg
= TPM2_ALG_SHA256
,
1047 TPMA_OBJECT_RESTRICTED
|
1048 TPMA_OBJECT_DECRYPT
|
1049 TPMA_OBJECT_FIXEDTPM
|
1050 TPMA_OBJECT_FIXEDPARENT
|
1051 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1052 TPMA_OBJECT_USERWITHAUTH
,
1053 .parameters
.eccDetail
= {
1055 .algorithm
= TPM2_ALG_AES
,
1057 .mode
.aes
= TPM2_ALG_CFB
,
1059 .scheme
.scheme
= TPM2_ALG_NULL
,
1060 .curveID
= TPM2_ECC_NIST_P256
,
1061 .kdf
.scheme
= TPM2_ALG_NULL
,
1065 /* Do not modify. */
1066 static const TPMT_PUBLIC legacy_rsa
= {
1067 .type
= TPM2_ALG_RSA
,
1068 .nameAlg
= TPM2_ALG_SHA256
,
1069 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
1070 .parameters
.rsaDetail
= {
1072 .algorithm
= TPM2_ALG_AES
,
1074 .mode
.aes
= TPM2_ALG_CFB
,
1076 .scheme
.scheme
= TPM2_ALG_NULL
,
1081 assert(ret_template
);
1083 if (alg
== TPM2_ALG_ECC
)
1084 *ret_template
= legacy_ecc
;
1085 else if (alg
== TPM2_ALG_RSA
)
1086 *ret_template
= legacy_rsa
;
1088 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1089 "Unsupported legacy SRK alg: 0x%x", alg
);
1094 /* Get a Storage Root Key (SRK) template.
1096 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1097 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1098 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1099 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1102 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1103 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1105 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1106 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1107 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1109 * The alg must be TPM2_ALG_RSA or TPM2_ALG_ECC. Returns error if the requested template is not supported on
1110 * this TPM. Also see tpm2_get_best_srk_template() below. */
1111 static int tpm2_get_srk_template(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1112 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1113 * Provisioning Guidance document, specifically:
1114 * TPMA_OBJECT_USERWITHAUTH is added.
1115 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1116 * TPMA_OBJECT_NODA is added. */
1117 TPMA_OBJECT srk_attributes
=
1118 TPMA_OBJECT_DECRYPT
|
1119 TPMA_OBJECT_FIXEDPARENT
|
1120 TPMA_OBJECT_FIXEDTPM
|
1122 TPMA_OBJECT_RESTRICTED
|
1123 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1124 TPMA_OBJECT_USERWITHAUTH
;
1126 /* The symmetric configuration is the same between ECC and RSA templates. */
1127 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1128 .algorithm
= TPM2_ALG_AES
,
1130 .mode
.aes
= TPM2_ALG_CFB
,
1133 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1135 /* From the EK Credential Profile template "L-2". */
1136 TPMT_PUBLIC srk_ecc
= {
1137 .type
= TPM2_ALG_ECC
,
1138 .nameAlg
= TPM2_ALG_SHA256
,
1139 .objectAttributes
= srk_attributes
,
1140 .parameters
.eccDetail
= {
1141 .symmetric
= srk_symmetric
,
1142 .scheme
.scheme
= TPM2_ALG_NULL
,
1143 .curveID
= TPM2_ECC_NIST_P256
,
1144 .kdf
.scheme
= TPM2_ALG_NULL
,
1148 /* From the EK Credential Profile template "L-1". */
1149 TPMT_PUBLIC srk_rsa
= {
1150 .type
= TPM2_ALG_RSA
,
1151 .nameAlg
= TPM2_ALG_SHA256
,
1152 .objectAttributes
= srk_attributes
,
1153 .parameters
.rsaDetail
= {
1154 .symmetric
= srk_symmetric
,
1155 .scheme
.scheme
= TPM2_ALG_NULL
,
1161 assert(ret_template
);
1163 if (alg
== TPM2_ALG_ECC
) {
1164 if (!tpm2_supports_alg(c
, TPM2_ALG_ECC
))
1165 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1166 "TPM does not support ECC.");
1168 if (!tpm2_supports_ecc_curve(c
, srk_ecc
.parameters
.eccDetail
.curveID
))
1169 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1170 "TPM does not support ECC-NIST-P256 curve.");
1172 if (!tpm2_supports_tpmt_public(c
, &srk_ecc
))
1173 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1174 "TPM does not support SRK ECC template L-2.");
1176 *ret_template
= srk_ecc
;
1180 if (alg
== TPM2_ALG_RSA
) {
1181 if (!tpm2_supports_alg(c
, TPM2_ALG_RSA
))
1182 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1183 "TPM does not support RSA.");
1185 if (!tpm2_supports_tpmt_public(c
, &srk_rsa
))
1186 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1187 "TPM does not support SRK RSA template L-1.");
1189 *ret_template
= srk_rsa
;
1193 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Unsupported SRK alg: 0x%x.", alg
);
1196 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1197 static int tpm2_get_best_srk_template(Tpm2Context
*c
, TPMT_PUBLIC
*ret_template
) {
1198 if (tpm2_get_srk_template(c
, TPM2_ALG_ECC
, ret_template
) >= 0 ||
1199 tpm2_get_srk_template(c
, TPM2_ALG_RSA
, ret_template
) >= 0)
1202 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1203 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1206 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1207 * tpm2_get_or_create_srk() below. */
1208 static int tpm2_get_srk(
1210 const Tpm2Handle
*session
,
1211 TPM2B_PUBLIC
**ret_public
,
1212 TPM2B_NAME
**ret_name
,
1213 TPM2B_NAME
**ret_qname
,
1214 Tpm2Handle
**ret_handle
) {
1216 return tpm2_index_to_handle(c
, TPM2_SRK_HANDLE
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1219 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1220 * exists, or < 0 on error. */
1221 int tpm2_get_or_create_srk(
1223 const Tpm2Handle
*session
,
1224 TPM2B_PUBLIC
**ret_public
,
1225 TPM2B_NAME
**ret_name
,
1226 TPM2B_NAME
**ret_qname
,
1227 Tpm2Handle
**ret_handle
) {
1231 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1235 return 0; /* 0 → SRK already set up */
1237 /* No SRK, create and persist one */
1238 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
1239 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1241 return log_debug_errno(r
, "Could not get best SRK template: %m");
1243 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1244 r
= tpm2_create_primary(
1248 /* sensitive= */ NULL
,
1249 /* ret_public= */ NULL
,
1254 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1255 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1256 * either case, all threads will get the persistent SRK below. */
1257 r
= tpm2_persist_handle(c
, transient_handle
, session
, TPM2_SRK_HANDLE
, /* ret_persistent_handle= */ NULL
);
1261 /* The SRK should exist now. */
1262 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1266 /* This should never happen. */
1267 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1269 return 1; /* > 0 → SRK newly set up */
1272 /* Utility functions for TPMS_PCR_SELECTION. */
1274 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1275 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1277 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1280 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1281 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
1285 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1286 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPMS_PCR_SELECTION
*ret
) {
1289 /* This is currently hardcoded at 24 PCRs, above. */
1290 if (!TPM2_PCR_MASK_VALID(mask
))
1291 log_debug("PCR mask selections (%x) out of range, ignoring.",
1292 mask
& ~((uint32_t)TPM2_PCRS_MASK
));
1294 *ret
= (TPMS_PCR_SELECTION
){
1296 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1297 .pcrSelect
[0] = mask
& 0xff,
1298 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1299 .pcrSelect
[2] = (mask
>> 16) & 0xff,
1303 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1304 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1307 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1310 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1313 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
1316 /* Add all PCR selections in the mask. */
1317 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1318 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 1);
1321 /* Remove all PCR selections in the mask. */
1322 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1323 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 0);
1326 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1327 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1330 assert(a
->hash
== b
->hash
);
1332 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1335 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1336 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1339 assert(a
->hash
== b
->hash
);
1341 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1344 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1345 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION
*a
, TPMS_PCR_SELECTION
*b
) {
1349 tpm2_tpms_pcr_selection_add(a
, b
);
1350 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
1353 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1354 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1355 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1356 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1357 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1359 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1360 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1362 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1363 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1364 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1366 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1369 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1371 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1375 return strjoin(algstr
, "(", mask
, ")");
1378 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1381 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1384 /* Utility functions for TPML_PCR_SELECTION. */
1386 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1387 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION
*l
, uint32_t index
) {
1389 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1390 assert(index
< l
->count
);
1392 size_t s
= l
->count
- (index
+ 1);
1393 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
1397 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1398 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1399 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1400 static TPMS_PCR_SELECTION
*tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1401 TPML_PCR_SELECTION
*l
,
1402 TPMI_ALG_HASH hash_alg
) {
1405 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1407 TPMS_PCR_SELECTION
*selection
= NULL
;
1408 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1409 if (s
->hash
== hash_alg
) {
1417 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1418 for (uint32_t i
= l
->count
- 1; i
> 0; i
--) {
1419 TPMS_PCR_SELECTION
*s
= &l
->pcrSelections
[i
];
1424 if (s
->hash
== hash_alg
) {
1425 tpm2_tpms_pcr_selection_move(selection
, s
);
1426 tpm2_tpml_pcr_selection_remove_index(l
, i
);
1433 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1434 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION
*l
) {
1435 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1436 for (uint32_t i
= 0; i
< l
->count
; i
++)
1437 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1438 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, l
->pcrSelections
[i
].hash
);
1441 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1442 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash_alg
) {
1445 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1446 * are multiple entries with the requested hash alg. */
1447 TPML_PCR_SELECTION lcopy
= *l
;
1449 TPMS_PCR_SELECTION
*s
;
1450 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1454 return tpm2_tpms_pcr_selection_to_mask(s
);
1457 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1458 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPML_PCR_SELECTION
*ret
) {
1461 TPMS_PCR_SELECTION s
;
1462 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1464 *ret
= (TPML_PCR_SELECTION
){
1466 .pcrSelections
[0] = s
,
1470 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1471 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1472 * entries with the same hash alg. */
1473 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1477 if (tpm2_tpms_pcr_selection_is_empty(s
))
1480 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1482 tpm2_tpms_pcr_selection_add(selection
, s
);
1486 /* It's already broken if the count is higher than the array has size for. */
1487 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1489 /* If full, the cleanup should result in at least one available entry. */
1490 if (l
->count
== ELEMENTSOF(l
->pcrSelections
))
1491 tpm2_tpml_pcr_selection_cleanup(l
);
1493 assert(l
->count
< ELEMENTSOF(l
->pcrSelections
));
1494 l
->pcrSelections
[l
->count
++] = *s
;
1497 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1498 * will combine all entries for 's->hash' in 'l'. */
1499 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1503 if (tpm2_tpms_pcr_selection_is_empty(s
))
1506 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1508 tpm2_tpms_pcr_selection_sub(selection
, s
);
1511 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1512 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1515 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l
, hash
), mask
);
1518 /* Add the PCR selections in the mask, with the provided hash. */
1519 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1520 TPMS_PCR_SELECTION tpms
;
1524 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1525 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l
, &tpms
);
1528 /* Remove the PCR selections in the mask, with the provided hash. */
1529 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1530 TPMS_PCR_SELECTION tpms
;
1534 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1535 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l
, &tpms
);
1538 /* Add all PCR selections in 'b' to 'a'. */
1539 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1543 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1544 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a
, selection_b
);
1547 /* Remove all PCR selections in 'b' from 'a'. */
1548 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1552 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1553 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a
, selection_b
);
1556 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION
*l
) {
1559 _cleanup_free_
char *banks
= NULL
;
1560 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1561 if (tpm2_tpms_pcr_selection_is_empty(s
))
1564 _cleanup_free_
char *str
= tpm2_tpms_pcr_selection_to_string(s
);
1565 if (!str
|| !strextend_with_separator(&banks
, ",", str
))
1569 return strjoin("[", strempty(banks
), "]");
1572 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION
*l
) {
1574 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1577 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1578 size_t w
= tpm2_tpms_pcr_selection_weight(s
);
1579 assert(weight
<= SIZE_MAX
- w
);
1586 bool tpm2_pcr_value_valid(const Tpm2PCRValue
*pcr_value
) {
1592 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1593 log_debug("PCR index %u invalid.", pcr_value
->index
);
1597 /* If it contains a value, the value size must match the hash size. */
1598 if (pcr_value
->value
.size
> 0) {
1599 r
= tpm2_hash_alg_to_size(pcr_value
->hash
);
1603 if (pcr_value
->value
.size
!= (size_t) r
) {
1604 log_debug("PCR hash 0x%" PRIx16
" expected size %d does not match actual size %" PRIu16
".",
1605 pcr_value
->hash
, r
, pcr_value
->value
.size
);
1613 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1615 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1616 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1618 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1620 bool tpm2_pcr_values_valid(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1621 if (!pcr_values
&& n_pcr_values
> 0)
1624 const Tpm2PCRValue
*previous
= NULL
;
1625 FOREACH_ARRAY(current
, pcr_values
, n_pcr_values
) {
1626 if (!tpm2_pcr_value_valid(current
))
1634 /* Hashes must be sorted in ascending order */
1635 if (current
->hash
< previous
->hash
) {
1636 log_debug("PCR values not in ascending order, hash %" PRIu16
" is after %" PRIu16
".",
1637 current
->hash
, previous
->hash
);
1641 if (current
->hash
== previous
->hash
) {
1642 /* Indexes (for the same hash) must be sorted in ascending order */
1643 if (current
->index
< previous
->index
) {
1644 log_debug("PCR values not in ascending order, hash %" PRIu16
" index %u is after %u.",
1645 current
->hash
, current
->index
, previous
->index
);
1649 /* Indexes (for the same hash) must not be duplicates */
1650 if (current
->index
== previous
->index
) {
1651 log_debug("PCR values contain duplicates for hash %" PRIu16
" index %u.",
1652 current
->hash
, previous
->index
);
1661 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1662 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1663 assert(pcr_values
|| n_pcr_values
== 0);
1665 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1666 if (v
->value
.size
> 0)
1672 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1673 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1674 assert(pcr_values
|| n_pcr_values
== 0);
1676 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1677 if (v
->value
.size
== 0)
1683 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1687 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
1690 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1691 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1692 void tpm2_sort_pcr_values(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1693 typesafe_qsort(pcr_values
, n_pcr_values
, cmp_pcr_values
);
1696 int tpm2_pcr_values_from_mask(uint32_t mask
, TPMI_ALG_HASH hash
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1697 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1698 size_t n_pcr_values
= 0;
1700 assert(ret_pcr_values
);
1701 assert(ret_n_pcr_values
);
1703 FOREACH_PCR_IN_MASK(index
, mask
)
1704 if (!GREEDY_REALLOC_APPEND(
1707 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1709 return log_oom_debug();
1711 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1712 *ret_n_pcr_values
= n_pcr_values
;
1717 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1720 assert(pcr_values
|| n_pcr_values
== 0);
1723 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1724 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1726 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1727 if (v
->hash
== hash
)
1728 SET_BIT(mask
, v
->index
);
1735 int tpm2_tpml_pcr_selection_from_pcr_values(
1736 const Tpm2PCRValue
*pcr_values
,
1737 size_t n_pcr_values
,
1738 TPML_PCR_SELECTION
*ret_selection
,
1739 TPM2B_DIGEST
**ret_values
,
1740 size_t *ret_n_values
) {
1742 TPML_PCR_SELECTION selection
= {};
1743 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1744 size_t n_values
= 0;
1746 assert(pcr_values
|| n_pcr_values
== 0);
1748 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1749 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR values are not valid.");
1751 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1752 tpm2_tpml_pcr_selection_add_mask(&selection
, v
->hash
, INDEX_TO_MASK(uint32_t, v
->index
));
1754 if (!GREEDY_REALLOC_APPEND(values
, n_values
, &v
->value
, 1))
1755 return log_oom_debug();
1759 *ret_selection
= selection
;
1761 *ret_values
= TAKE_PTR(values
);
1763 *ret_n_values
= n_values
;
1768 /* Count the number of different hash algorithms for all the entries. */
1769 int tpm2_pcr_values_hash_count(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, size_t *ret_count
) {
1770 TPML_PCR_SELECTION selection
;
1776 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1780 /* ret_values= */ NULL
,
1781 /* ret_n_values= */ NULL
);
1785 *ret_count
= selection
.count
;
1790 /* Parse a string argument into a Tpm2PCRValue object.
1792 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1793 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1794 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1795 int tpm2_pcr_value_from_string(const char *arg
, Tpm2PCRValue
*ret_pcr_value
) {
1796 Tpm2PCRValue pcr_value
= {};
1797 const char *p
= arg
;
1801 assert(ret_pcr_value
);
1803 _cleanup_free_
char *index
= NULL
;
1804 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1806 return log_debug_errno(r
, "Could not parse pcr value '%s': %m", p
);
1808 r
= tpm2_pcr_index_from_string(index
);
1810 return log_debug_errno(r
, "Invalid pcr index '%s': %m", index
);
1811 pcr_value
.index
= (unsigned) r
;
1814 _cleanup_free_
char *hash
= NULL
;
1815 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1817 return log_debug_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1819 r
= tpm2_hash_alg_from_string(hash
);
1821 return log_debug_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1822 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1825 /* Remove leading 0x if present */
1826 p
= startswith_no_case(p
, "0x") ?: p
;
1828 _cleanup_free_
void *buf
= NULL
;
1829 size_t buf_size
= 0;
1830 r
= unhexmem(p
, SIZE_MAX
, &buf
, &buf_size
);
1832 return log_debug_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1834 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1836 return log_debug_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1838 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1842 *ret_pcr_value
= pcr_value
;
1847 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1848 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1849 * string. This does not check for validity. */
1850 char *tpm2_pcr_value_to_string(const Tpm2PCRValue
*pcr_value
) {
1851 _cleanup_free_
char *index
= NULL
, *value
= NULL
;
1853 if (asprintf(&index
, "%u", pcr_value
->index
) < 0)
1856 const char *hash
= pcr_value
->hash
> 0 ? tpm2_hash_alg_to_string(pcr_value
->hash
) : NULL
;
1858 if (hash
&& pcr_value
->value
.size
> 0) {
1859 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1864 return strjoin(index
, hash
? ":" : "", strempty(hash
), value
? "=" : "", strempty(value
));
1867 /* Parse a string argument into an array of Tpm2PCRValue objects.
1869 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1870 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1871 int tpm2_pcr_values_from_string(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1872 const char *p
= arg
;
1876 assert(ret_pcr_values
);
1877 assert(ret_n_pcr_values
);
1879 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1880 size_t n_pcr_values
= 0;
1883 _cleanup_free_
char *pcr_arg
= NULL
;
1884 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1886 return log_debug_errno(r
, "Could not parse pcr values '%s': %m", p
);
1890 Tpm2PCRValue pcr_value
;
1891 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1895 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1896 return log_oom_debug();
1899 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1900 *ret_n_pcr_values
= n_pcr_values
;
1905 /* Return a string representing the array of PCR values. The format is as described in
1906 * tpm2_pcr_values_from_string(). This does not check for validity. */
1907 char *tpm2_pcr_values_to_string(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1908 _cleanup_free_
char *s
= NULL
;
1910 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1911 _cleanup_free_
char *pcrstr
= tpm2_pcr_value_to_string(v
);
1912 if (!pcrstr
|| !strextend_with_separator(&s
, "+", pcrstr
))
1916 return s
? TAKE_PTR(s
) : strdup("");
1919 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
1920 if (!DEBUG_LOGGING
|| !l
)
1923 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
1924 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
1927 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
1928 if (!DEBUG_LOGGING
|| !pcr_value
)
1931 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
1932 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
1935 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
1936 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
1939 _cleanup_free_
char *h
= hexmem(buffer
, size
);
1940 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
1943 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
1945 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
1948 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
1950 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
1953 static int tpm2_get_policy_digest(
1955 const Tpm2Handle
*session
,
1956 TPM2B_DIGEST
**ret_policy_digest
) {
1960 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
1966 log_debug("Acquiring policy digest.");
1968 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
1969 rc
= sym_Esys_PolicyGetDigest(
1971 session
->esys_handle
,
1976 if (rc
!= TSS2_RC_SUCCESS
)
1977 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1978 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc
));
1980 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
1982 if (ret_policy_digest
)
1983 *ret_policy_digest
= TAKE_PTR(policy_digest
);
1988 int tpm2_create_primary(
1990 const Tpm2Handle
*session
,
1991 const TPM2B_PUBLIC
*template,
1992 const TPM2B_SENSITIVE_CREATE
*sensitive
,
1993 TPM2B_PUBLIC
**ret_public
,
1994 Tpm2Handle
**ret_handle
) {
2003 log_debug("Creating primary key on TPM.");
2005 ts
= now(CLOCK_MONOTONIC
);
2007 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2008 r
= tpm2_handle_new(c
, &handle
);
2012 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2013 rc
= sym_Esys_CreatePrimary(
2016 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2019 sensitive
? sensitive
: &(TPM2B_SENSITIVE_CREATE
) {},
2021 /* outsideInfo= */ NULL
,
2022 &(TPML_PCR_SELECTION
) {},
2023 &handle
->esys_handle
,
2025 /* creationData= */ NULL
,
2026 /* creationHash= */ NULL
,
2027 /* creationTicket= */ NULL
);
2028 if (rc
!= TSS2_RC_SUCCESS
)
2029 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2030 "Failed to generate primary key in TPM: %s",
2031 sym_Tss2_RC_Decode(rc
));
2033 log_debug("Successfully created primary key on TPM in %s.",
2034 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2037 *ret_public
= TAKE_PTR(public);
2039 *ret_handle
= TAKE_PTR(handle
);
2044 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2045 * instead use tpm2_create_primary(). */
2046 int tpm2_create(Tpm2Context
*c
,
2047 const Tpm2Handle
*parent
,
2048 const Tpm2Handle
*session
,
2049 const TPMT_PUBLIC
*template,
2050 const TPMS_SENSITIVE_CREATE
*sensitive
,
2051 TPM2B_PUBLIC
**ret_public
,
2052 TPM2B_PRIVATE
**ret_private
) {
2061 log_debug("Creating object on TPM.");
2063 ts
= now(CLOCK_MONOTONIC
);
2065 TPM2B_PUBLIC tpm2b_public
= {
2066 .size
= sizeof(*template) - sizeof(template->unique
),
2067 .publicArea
= *template,
2070 /* Zero the unique area. */
2071 zero(tpm2b_public
.publicArea
.unique
);
2073 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2075 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2076 .size
= sizeof(*sensitive
),
2077 .sensitive
= *sensitive
,
2080 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2082 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2083 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2084 rc
= sym_Esys_Create(
2086 parent
->esys_handle
,
2087 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2092 /* outsideInfo= */ NULL
,
2093 &(TPML_PCR_SELECTION
) {},
2096 /* creationData= */ NULL
,
2097 /* creationHash= */ NULL
,
2098 /* creationTicket= */ NULL
);
2099 if (rc
!= TSS2_RC_SUCCESS
)
2100 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2101 "Failed to generate object in TPM: %s",
2102 sym_Tss2_RC_Decode(rc
));
2104 log_debug("Successfully created object on TPM in %s.",
2105 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2108 *ret_public
= TAKE_PTR(public);
2110 *ret_private
= TAKE_PTR(private);
2115 static int tpm2_load(
2117 const Tpm2Handle
*parent
,
2118 const Tpm2Handle
*session
,
2119 const TPM2B_PUBLIC
*public,
2120 const TPM2B_PRIVATE
*private,
2121 Tpm2Handle
**ret_handle
) {
2131 log_debug("Loading object into TPM.");
2133 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2134 r
= tpm2_handle_new(c
, &handle
);
2140 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2141 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2146 &handle
->esys_handle
);
2147 if (rc
== TPM2_RC_LOCKOUT
)
2148 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK
),
2149 "TPM2 device is in dictionary attack lockout mode.");
2150 if (rc
!= TSS2_RC_SUCCESS
)
2151 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2152 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2154 *ret_handle
= TAKE_PTR(handle
);
2159 static int tpm2_load_external(
2161 const Tpm2Handle
*session
,
2162 const TPM2B_PUBLIC
*public,
2163 const TPM2B_SENSITIVE
*private,
2164 Tpm2Handle
**ret_handle
) {
2172 log_debug("Loading external key into TPM.");
2174 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2175 r
= tpm2_handle_new(c
, &handle
);
2179 rc
= sym_Esys_LoadExternal(
2181 session
? session
->esys_handle
: ESYS_TR_NONE
,
2187 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2188 * hierarchy, older versions need TPM2_RH_* instead. */
2193 &handle
->esys_handle
);
2194 if (rc
!= TSS2_RC_SUCCESS
)
2195 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2196 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2198 *ret_handle
= TAKE_PTR(handle
);
2203 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2204 * use tpm2_create_loaded(). */
2205 static int _tpm2_create_loaded(
2207 const Tpm2Handle
*parent
,
2208 const Tpm2Handle
*session
,
2209 const TPMT_PUBLIC
*template,
2210 const TPMS_SENSITIVE_CREATE
*sensitive
,
2211 TPM2B_PUBLIC
**ret_public
,
2212 TPM2B_PRIVATE
**ret_private
,
2213 Tpm2Handle
**ret_handle
) {
2223 log_debug("Creating loaded object on TPM.");
2225 ts
= now(CLOCK_MONOTONIC
);
2227 /* Copy the input template and zero the unique area. */
2228 TPMT_PUBLIC template_copy
= *template;
2229 zero(template_copy
.unique
);
2231 TPM2B_TEMPLATE tpm2b_template
;
2233 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2235 tpm2b_template
.buffer
,
2236 sizeof(tpm2b_template
.buffer
),
2238 if (rc
!= TSS2_RC_SUCCESS
)
2239 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2240 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc
));
2241 assert(size
<= UINT16_MAX
);
2242 tpm2b_template
.size
= size
;
2244 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2246 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2247 .size
= sizeof(*sensitive
),
2248 .sensitive
= *sensitive
,
2251 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2253 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2254 r
= tpm2_handle_new(c
, &handle
);
2258 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2259 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2260 rc
= sym_Esys_CreateLoaded(
2262 parent
->esys_handle
,
2263 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2268 &handle
->esys_handle
,
2271 if (rc
!= TSS2_RC_SUCCESS
)
2272 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2273 "Failed to generate loaded object in TPM: %s",
2274 sym_Tss2_RC_Decode(rc
));
2276 log_debug("Successfully created loaded object on TPM in %s.",
2277 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2280 *ret_public
= TAKE_PTR(public);
2282 *ret_private
= TAKE_PTR(private);
2284 *ret_handle
= TAKE_PTR(handle
);
2289 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2290 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2291 * tpm2_create_primary(). */
2292 int tpm2_create_loaded(
2294 const Tpm2Handle
*parent
,
2295 const Tpm2Handle
*session
,
2296 const TPMT_PUBLIC
*template,
2297 const TPMS_SENSITIVE_CREATE
*sensitive
,
2298 TPM2B_PUBLIC
**ret_public
,
2299 TPM2B_PRIVATE
**ret_private
,
2300 Tpm2Handle
**ret_handle
) {
2304 if (tpm2_supports_command(c
, TPM2_CC_CreateLoaded
))
2305 return _tpm2_create_loaded(c
, parent
, session
, template, sensitive
, ret_public
, ret_private
, ret_handle
);
2307 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2308 * create and load manually. */
2309 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2310 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2311 r
= tpm2_create(c
, parent
, session
, template, sensitive
, &public, &private);
2315 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2316 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2321 *ret_public
= TAKE_PTR(public);
2323 *ret_private
= TAKE_PTR(private);
2325 *ret_handle
= TAKE_PTR(handle
);
2330 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2331 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2332 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2333 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2337 const TPML_PCR_SELECTION
*pcr_selection
,
2338 Tpm2PCRValue
**ret_pcr_values
,
2339 size_t *ret_n_pcr_values
) {
2341 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2342 size_t n_pcr_values
= 0;
2346 assert(pcr_selection
);
2347 assert(ret_pcr_values
);
2348 assert(ret_n_pcr_values
);
2350 TPML_PCR_SELECTION remaining
= *pcr_selection
;
2351 while (!tpm2_tpml_pcr_selection_is_empty(&remaining
)) {
2352 _cleanup_(Esys_Freep
) TPML_PCR_SELECTION
*current_read
= NULL
;
2353 _cleanup_(Esys_Freep
) TPML_DIGEST
*current_values
= NULL
;
2355 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2357 /* Unfortunately, PCR_Read will not return more than 8 values. */
2358 rc
= sym_Esys_PCR_Read(
2367 if (rc
!= TSS2_RC_SUCCESS
)
2368 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2369 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc
));
2371 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2373 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2374 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2379 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2380 assert(i
< current_values
->count
);
2381 Tpm2PCRValue pcr_value
= {
2384 .value
= current_values
->digests
[i
++],
2387 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2389 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2390 return log_oom_debug();
2392 assert(i
== current_values
->count
);
2394 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2397 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
2399 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
2400 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "PCR values read from TPM are not valid.");
2402 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2403 *ret_n_pcr_values
= n_pcr_values
;
2408 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2409 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2410 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2411 * appropriate entries, this returns an error. This does not check the array for validity. */
2412 int tpm2_pcr_read_missing_values(Tpm2Context
*c
, Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2413 TPMI_ALG_HASH pcr_bank
= 0;
2417 assert(pcr_values
|| n_pcr_values
== 0);
2419 if (n_pcr_values
> 0) {
2421 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2423 return log_debug_errno(r
, "Could not get hash count from pcr values: %m");
2425 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2427 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2431 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2437 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2441 if (v
->value
.size
> 0)
2444 TPML_PCR_SELECTION selection
;
2445 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
2449 _cleanup_free_ Tpm2PCRValue
*read_values
= NULL
;
2450 size_t n_read_values
;
2451 r
= tpm2_pcr_read(c
, &selection
, &read_values
, &n_read_values
);
2455 if (n_read_values
== 0)
2456 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2457 "Could not read PCR hash 0x%" PRIu16
" index %u",
2460 assert(n_read_values
== 1);
2461 assert(read_values
[0].hash
== v
->hash
);
2462 assert(read_values
[0].index
== v
->index
);
2464 v
->value
= read_values
[0].value
;
2470 static int tpm2_pcr_mask_good(
2475 TPML_PCR_SELECTION selection
;
2480 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2481 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2482 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2484 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
2486 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2487 size_t n_pcr_values
;
2488 r
= tpm2_pcr_read(c
, &selection
, &pcr_values
, &n_pcr_values
);
2492 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2493 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
2494 if (!memeqbyte(0x00, v
->value
.buffer
, v
->value
.size
) &&
2495 !memeqbyte(0xFF, v
->value
.buffer
, v
->value
.size
))
2501 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
2505 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2506 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2507 if (selection
->sizeofSelect
< TPM2_PCRS_MAX
/8) {
2508 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2509 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2513 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
2515 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2516 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2518 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2519 if (selection
->pcrSelect
[j
] != 0xFF) {
2525 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2526 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2531 int tpm2_get_best_pcr_bank(
2534 TPMI_ALG_HASH
*ret
) {
2536 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
2542 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2543 TPMI_ALG_HASH hash
= selection
->hash
;
2546 /* For now we are only interested in the SHA1 and SHA256 banks */
2547 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2550 r
= tpm2_bank_has24(selection
);
2556 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2560 if (hash
== TPM2_ALG_SHA256
) {
2561 supported_hash
= TPM2_ALG_SHA256
;
2563 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2564 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2568 assert(hash
== TPM2_ALG_SHA1
);
2570 if (supported_hash
== 0)
2571 supported_hash
= TPM2_ALG_SHA1
;
2573 if (good
&& hash_with_valid_pcr
== 0)
2574 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
2578 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2579 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2582 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2583 * not initialized. */
2585 if (hash_with_valid_pcr
== TPM2_ALG_SHA256
) {
2586 assert(supported_hash
== TPM2_ALG_SHA256
);
2587 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2588 *ret
= TPM2_ALG_SHA256
;
2589 } else if (hash_with_valid_pcr
== TPM2_ALG_SHA1
) {
2590 if (supported_hash
== TPM2_ALG_SHA256
)
2591 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.");
2593 assert(supported_hash
== TPM2_ALG_SHA1
);
2594 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.");
2597 *ret
= TPM2_ALG_SHA1
;
2598 } else if (supported_hash
== TPM2_ALG_SHA256
) {
2599 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!");
2600 *ret
= TPM2_ALG_SHA256
;
2601 } else if (supported_hash
== TPM2_ALG_SHA1
) {
2602 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!");
2603 *ret
= TPM2_ALG_SHA1
;
2605 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2606 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2611 int tpm2_get_good_pcr_banks(
2614 TPMI_ALG_HASH
**ret
) {
2616 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2617 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2623 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2624 TPMI_ALG_HASH hash
= selection
->hash
;
2626 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2627 r
= tpm2_bank_has24(selection
);
2633 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2634 r
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2638 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2639 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2642 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2643 return log_oom_debug();
2645 good_banks
[n_good_banks
++] = hash
;
2647 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2648 return log_oom_debug();
2650 fallback_banks
[n_fallback_banks
++] = hash
;
2654 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2655 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2656 if (n_good_banks
> 0) {
2657 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks
);
2658 *ret
= TAKE_PTR(good_banks
);
2659 return (int) n_good_banks
;
2661 if (n_fallback_banks
> 0) {
2662 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks
);
2663 *ret
= TAKE_PTR(fallback_banks
);
2664 return (int) n_fallback_banks
;
2667 /* No suitable banks found. */
2672 int tpm2_get_good_pcr_banks_strv(
2678 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2679 _cleanup_strv_free_
char **l
= NULL
;
2685 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2689 FOREACH_ARRAY(a
, algs
, n_algs
) {
2690 _cleanup_free_
char *n
= NULL
;
2691 const EVP_MD
*implementation
;
2694 salg
= tpm2_hash_alg_to_string(*a
);
2696 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
2698 implementation
= EVP_get_digestbyname(salg
);
2699 if (!implementation
)
2700 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2702 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2704 return log_oom_debug();
2706 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2708 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2709 return log_oom_debug();
2714 #else /* HAVE_OPENSSL */
2715 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2719 /* Hash data into the digest.
2721 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2722 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2723 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2724 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2726 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2727 * correct for 'alg'.
2729 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2730 int tpm2_digest_many(
2732 TPM2B_DIGEST
*digest
,
2733 const struct iovec data
[],
2737 struct sha256_ctx ctx
;
2740 assert(data
|| n_data
== 0);
2742 if (alg
!= TPM2_ALG_SHA256
)
2743 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2744 "Hash algorithm not supported: 0x%x", alg
);
2746 if (extend
&& digest
->size
!= SHA256_DIGEST_SIZE
)
2747 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2748 "Digest size 0x%x, require 0x%x",
2749 digest
->size
, (unsigned)SHA256_DIGEST_SIZE
);
2751 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2752 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
2756 sha256_init_ctx(&ctx
);
2759 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
2761 *digest
= (TPM2B_DIGEST
){ .size
= SHA256_DIGEST_SIZE
, };
2762 if (n_data
== 0) /* If not extending and no data, return zero hash */
2766 FOREACH_ARRAY(d
, data
, n_data
)
2767 sha256_process_bytes(d
->iov_base
, d
->iov_len
, &ctx
);
2769 sha256_finish_ctx(&ctx
, digest
->buffer
);
2774 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2775 int tpm2_digest_many_digests(
2777 TPM2B_DIGEST
*digest
,
2778 const TPM2B_DIGEST data
[],
2782 _cleanup_free_
struct iovec
*iovecs
= NULL
;
2784 assert(data
|| n_data
== 0);
2786 iovecs
= new(struct iovec
, n_data
);
2788 return log_oom_debug();
2790 for (size_t i
= 0; i
< n_data
; i
++)
2791 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
2793 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
2796 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
2797 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
2798 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
2799 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
2800 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2802 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2803 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2804 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2805 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2807 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2808 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2809 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2811 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2812 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2813 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2814 * which we will trim the 0(s) from before sending to the TPM.
2816 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
2817 bool trimmed
= false;
2821 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
2827 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2830 static int tpm2_get_pin_auth(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
2831 TPM2B_AUTH auth
= {};
2837 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
2841 tpm2_trim_auth_value(&auth
);
2843 *ret_auth
= TAKE_STRUCT(auth
);
2848 static int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
2849 TPM2B_AUTH auth
= {};
2859 CLEANUP_ERASE(auth
);
2861 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &auth
);
2865 rc
= sym_Esys_TR_SetAuth(c
->esys_context
, handle
->esys_handle
, &auth
);
2866 if (rc
!= TSS2_RC_SUCCESS
)
2867 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2868 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc
));
2873 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
2874 TPMA_SESSION flags
= 0;
2880 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
2881 if (rc
!= TSS2_RC_SUCCESS
)
2884 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
2887 static int tpm2_make_encryption_session(
2889 const Tpm2Handle
*primary
,
2890 const Tpm2Handle
*bind_key
,
2891 Tpm2Handle
**ret_session
) {
2893 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
2894 TPMA_SESSION_CONTINUESESSION
;
2900 assert(ret_session
);
2902 log_debug("Starting HMAC encryption session.");
2904 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2905 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2906 * recover the salt, which is then used for key derivation. */
2907 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2908 r
= tpm2_handle_new(c
, &session
);
2912 rc
= sym_Esys_StartAuthSession(
2914 primary
->esys_handle
,
2915 bind_key
? bind_key
->esys_handle
: ESYS_TR_NONE
,
2921 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2923 &session
->esys_handle
);
2924 if (rc
!= TSS2_RC_SUCCESS
)
2925 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2926 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2928 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2929 * always used for sessions), this provides confidentiality, integrity and replay protection for
2930 * operations that use this session. */
2931 rc
= sym_Esys_TRSess_SetAttributes(c
->esys_context
, session
->esys_handle
, sessionAttributes
, 0xff);
2932 if (rc
!= TSS2_RC_SUCCESS
)
2933 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2934 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc
));
2936 *ret_session
= TAKE_PTR(session
);
2941 static int tpm2_make_policy_session(
2943 const Tpm2Handle
*primary
,
2944 const Tpm2Handle
*encryption_session
,
2945 Tpm2Handle
**ret_session
) {
2952 assert(encryption_session
);
2953 assert(ret_session
);
2955 if (!tpm2_is_encryption_session(c
, encryption_session
))
2956 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
2957 "Missing encryption session");
2959 log_debug("Starting policy session.");
2961 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2962 r
= tpm2_handle_new(c
, &session
);
2966 rc
= sym_Esys_StartAuthSession(
2968 primary
->esys_handle
,
2970 encryption_session
->esys_handle
,
2975 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2977 &session
->esys_handle
);
2978 if (rc
!= TSS2_RC_SUCCESS
)
2979 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2980 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2982 *ret_session
= TAKE_PTR(session
);
2987 static int find_signature(
2989 const TPML_PCR_SELECTION
*pcr_selection
,
2994 void *ret_signature
,
2995 size_t *ret_signature_size
) {
3002 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3003 * public key, and policy digest. */
3005 if (!json_variant_is_object(v
))
3006 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
3008 uint16_t pcr_bank
= pcr_selection
->pcrSelections
[0].hash
;
3009 uint32_t pcr_mask
= tpm2_tpml_pcr_selection_to_mask(pcr_selection
, pcr_bank
);
3011 k
= tpm2_hash_alg_to_string(pcr_bank
);
3013 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
3015 /* First, find field by bank */
3016 b
= json_variant_by_key(v
, k
);
3018 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
3020 if (!json_variant_is_array(b
))
3021 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
3023 /* Now iterate through all signatures known for this bank */
3024 JSON_VARIANT_ARRAY_FOREACH(i
, b
) {
3025 _cleanup_free_
void *fpj_data
= NULL
, *polj_data
= NULL
;
3026 JsonVariant
*maskj
, *fpj
, *sigj
, *polj
;
3027 size_t fpj_size
, polj_size
;
3028 uint32_t parsed_mask
;
3030 if (!json_variant_is_object(i
))
3031 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
3033 /* Check if the PCR mask matches our expectations */
3034 maskj
= json_variant_by_key(i
, "pcrs");
3038 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
3040 return log_debug_errno(r
, "Failed to parse JSON PCR mask");
3042 if (parsed_mask
!= pcr_mask
)
3043 continue; /* Not for this PCR mask */
3045 /* Then check if this is for the public key we operate with */
3046 fpj
= json_variant_by_key(i
, "pkfp");
3050 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
3052 return log_debug_errno(r
, "Failed to decode fingerprint in JSON data: %m");
3054 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
3055 continue; /* Not for this public key */
3057 /* Finally, check if this is for the PCR policy we expect this to be */
3058 polj
= json_variant_by_key(i
, "pol");
3062 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
3064 return log_debug_errno(r
, "Failed to decode policy hash JSON data: %m");
3066 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
3069 /* This entry matches all our expectations, now return the signature included in it */
3070 sigj
= json_variant_by_key(i
, "sig");
3074 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
3077 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Couldn't find signature for this PCR bank, PCR index and public key.");
3078 #else /* HAVE_OPENSSL */
3079 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3083 /* Calculates the "name" of a public key.
3085 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3086 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3087 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3088 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3089 * that would also change the key name.
3091 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3092 * nameAlg is not TPM2_ALG_SHA256. */
3093 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC
*public, TPM2B_NAME
*ret_name
) {
3102 return log_debug_errno(r
, "TPM2 support not installed: %m");
3104 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3105 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3106 "Unsupported nameAlg: 0x%x",
3109 _cleanup_free_
uint8_t *buf
= NULL
;
3112 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3114 return log_oom_debug();
3116 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf
, sizeof(TPMT_PUBLIC
), &size
);
3117 if (rc
!= TSS2_RC_SUCCESS
)
3118 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3119 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3121 TPM2B_DIGEST digest
= {};
3122 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3127 .hashAlg
= TPM2_ALG_SHA256
,
3129 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3130 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3134 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3135 if (rc
!= TSS2_RC_SUCCESS
)
3136 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3137 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc
));
3140 tpm2_log_debug_name(&name
, "Calculated name");
3147 /* Get the "name" of a key from the TPM.
3149 * The "name" of a key is explained above in tpm2_calculate_name().
3151 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3152 * public/private keypair. */
3153 static int tpm2_get_name(
3155 const Tpm2Handle
*handle
,
3156 TPM2B_NAME
**ret_name
) {
3158 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
3165 rc
= sym_Esys_TR_GetName(c
->esys_context
, handle
->esys_handle
, &name
);
3166 if (rc
!= TSS2_RC_SUCCESS
)
3167 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3168 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc
));
3170 tpm2_log_debug_name(name
, "Object name");
3172 *ret_name
= TAKE_PTR(name
);
3177 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3178 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST
*digest
) {
3179 TPM2_CC command
= TPM2_CC_PolicyAuthValue
;
3184 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3188 return log_debug_errno(r
, "TPM2 support not installed: %m");
3190 uint8_t buf
[sizeof(command
)];
3193 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3194 if (rc
!= TSS2_RC_SUCCESS
)
3195 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3196 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc
));
3198 if (offset
!= sizeof(command
))
3199 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3200 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3202 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3206 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3211 static int tpm2_policy_auth_value(
3213 const Tpm2Handle
*session
,
3214 TPM2B_DIGEST
**ret_policy_digest
) {
3221 log_debug("Adding authValue policy.");
3223 rc
= sym_Esys_PolicyAuthValue(
3225 session
->esys_handle
,
3229 if (rc
!= TSS2_RC_SUCCESS
)
3230 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3231 "Failed to add authValue policy to TPM: %s",
3232 sym_Tss2_RC_Decode(rc
));
3234 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3237 /* Extend 'digest' with the PolicyPCR calculated hash. */
3238 int tpm2_calculate_policy_pcr(
3239 const Tpm2PCRValue
*pcr_values
,
3240 size_t n_pcr_values
,
3241 TPM2B_DIGEST
*digest
) {
3243 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3247 assert(pcr_values
|| n_pcr_values
== 0);
3249 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3253 return log_debug_errno(r
, "TPM2 support not installed: %m");
3255 TPML_PCR_SELECTION pcr_selection
;
3256 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3258 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3260 return log_debug_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3262 TPM2B_DIGEST hash
= {};
3263 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3267 _cleanup_free_
uint8_t *buf
= NULL
;
3268 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3270 buf
= malloc(maxsize
);
3272 return log_oom_debug();
3274 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, maxsize
, &size
);
3275 if (rc
!= TSS2_RC_SUCCESS
)
3276 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3277 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc
));
3279 rc
= sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection
, buf
, maxsize
, &size
);
3280 if (rc
!= TSS2_RC_SUCCESS
)
3281 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3282 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc
));
3284 struct iovec data
[] = {
3285 IOVEC_MAKE(buf
, size
),
3286 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3288 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3292 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3297 static int tpm2_policy_pcr(
3299 const Tpm2Handle
*session
,
3300 const TPML_PCR_SELECTION
*pcr_selection
,
3301 TPM2B_DIGEST
**ret_policy_digest
) {
3307 assert(pcr_selection
);
3309 log_debug("Adding PCR hash policy.");
3311 rc
= sym_Esys_PolicyPCR(
3313 session
->esys_handle
,
3319 if (rc
!= TSS2_RC_SUCCESS
)
3320 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3321 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc
));
3323 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3326 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3327 int tpm2_calculate_policy_authorize(
3328 const TPM2B_PUBLIC
*public,
3329 const TPM2B_DIGEST
*policy_ref
,
3330 TPM2B_DIGEST
*digest
) {
3332 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3338 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3342 return log_debug_errno(r
, "TPM2 support not installed: %m");
3344 uint8_t buf
[sizeof(command
)];
3347 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3348 if (rc
!= TSS2_RC_SUCCESS
)
3349 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3350 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc
));
3352 if (offset
!= sizeof(command
))
3353 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3354 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
3356 TPM2B_NAME name
= {};
3357 r
= tpm2_calculate_pubkey_name(&public->publicArea
, &name
);
3361 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3362 zero(digest
->buffer
);
3364 struct iovec data
[] = {
3365 IOVEC_MAKE(buf
, offset
),
3366 IOVEC_MAKE(name
.name
, name
.size
),
3368 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3372 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3374 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
3376 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
3380 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
3385 static int tpm2_policy_authorize(
3387 const Tpm2Handle
*session
,
3388 TPML_PCR_SELECTION
*pcr_selection
,
3389 const TPM2B_PUBLIC
*public,
3392 JsonVariant
*signature_json
,
3393 TPM2B_DIGEST
**ret_policy_digest
) {
3400 assert(pcr_selection
);
3402 assert(fp
&& fp_size
> 0);
3404 log_debug("Adding PCR signature policy.");
3406 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
3407 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
3411 /* Acquire the "name" of what we just loaded */
3412 _cleanup_(Esys_Freep
) TPM2B_NAME
*pubkey_name
= NULL
;
3413 r
= tpm2_get_name(c
, pubkey_handle
, &pubkey_name
);
3417 /* If we have a signature, proceed with verifying the PCR digest */
3418 const TPMT_TK_VERIFIED
*check_ticket
;
3419 _cleanup_(Esys_Freep
) TPMT_TK_VERIFIED
*check_ticket_buffer
= NULL
;
3420 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*approved_policy
= NULL
;
3421 if (signature_json
) {
3422 r
= tpm2_policy_pcr(
3430 _cleanup_free_
void *signature_raw
= NULL
;
3431 size_t signature_size
;
3437 approved_policy
->buffer
,
3438 approved_policy
->size
,
3444 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3445 * hence we need to do the SHA256 part ourselves, first */
3446 TPM2B_DIGEST signature_hash
= *approved_policy
;
3447 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, &signature_hash
);
3451 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
3453 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
3455 TPMT_SIGNATURE policy_signature
= {
3456 .sigAlg
= TPM2_ALG_RSASSA
,
3457 .signature
.rsassa
= {
3458 .hash
= TPM2_ALG_SHA256
,
3459 .sig
= TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw
, signature_size
),
3463 rc
= sym_Esys_VerifySignature(
3465 pubkey_handle
->esys_handle
,
3471 &check_ticket_buffer
);
3472 if (rc
!= TSS2_RC_SUCCESS
)
3473 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3474 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc
));
3476 check_ticket
= check_ticket_buffer
;
3478 /* When enrolling, we pass a NULL ticket */
3479 static const TPMT_TK_VERIFIED check_ticket_null
= {
3480 .tag
= TPM2_ST_VERIFIED
,
3481 .hierarchy
= TPM2_RH_OWNER
,
3484 check_ticket
= &check_ticket_null
;
3487 rc
= sym_Esys_PolicyAuthorize(
3489 session
->esys_handle
,
3494 /* policyRef= */ &(const TPM2B_NONCE
) {},
3497 if (rc
!= TSS2_RC_SUCCESS
)
3498 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3499 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc
));
3501 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3504 /* Extend 'digest' with the calculated policy hash. */
3505 int tpm2_calculate_sealing_policy(
3506 const Tpm2PCRValue
*pcr_values
,
3507 size_t n_pcr_values
,
3508 const TPM2B_PUBLIC
*public,
3510 TPM2B_DIGEST
*digest
) {
3514 assert(pcr_values
|| n_pcr_values
== 0);
3518 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
3523 if (n_pcr_values
> 0) {
3524 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
3530 r
= tpm2_calculate_policy_auth_value(digest
);
3538 static int tpm2_build_sealing_policy(
3540 const Tpm2Handle
*session
,
3541 uint32_t hash_pcr_mask
,
3543 const TPM2B_PUBLIC
*public,
3546 uint32_t pubkey_pcr_mask
,
3547 JsonVariant
*signature_json
,
3549 TPM2B_DIGEST
**ret_policy_digest
) {
3555 assert(pubkey_pcr_mask
== 0 || public);
3557 log_debug("Building sealing policy.");
3559 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
3560 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
3564 log_debug("Selected TPM2 PCRs are not initialized on this system.");
3567 if (pubkey_pcr_mask
!= 0) {
3568 TPML_PCR_SELECTION pcr_selection
;
3569 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3570 r
= tpm2_policy_authorize(c
, session
, &pcr_selection
, public, fp
, fp_size
, signature_json
, NULL
);
3575 if (hash_pcr_mask
!= 0) {
3576 TPML_PCR_SELECTION pcr_selection
;
3577 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3578 r
= tpm2_policy_pcr(c
, session
, &pcr_selection
, NULL
);
3584 r
= tpm2_policy_auth_value(c
, session
, NULL
);
3589 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3597 static const struct {
3598 TPM2_ECC_CURVE tpm2_ecc_curve_id
;
3599 int openssl_ecc_curve_id
;
3600 } tpm2_openssl_ecc_curve_table
[] = {
3601 { TPM2_ECC_NIST_P192
, NID_X9_62_prime192v1
, },
3602 { TPM2_ECC_NIST_P224
, NID_secp224r1
, },
3603 { TPM2_ECC_NIST_P256
, NID_X9_62_prime256v1
, },
3604 { TPM2_ECC_NIST_P384
, NID_secp384r1
, },
3605 { TPM2_ECC_NIST_P521
, NID_secp521r1
, },
3606 { TPM2_ECC_SM2_P256
, NID_sm2
, },
3609 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id
, TPM2_ECC_CURVE
*ret
) {
3612 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
3613 if (t
->openssl_ecc_curve_id
== openssl_ecc_curve_id
) {
3614 *ret
= t
->tpm2_ecc_curve_id
;
3618 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3619 "Openssl ECC curve id %d not supported.", openssl_ecc_curve_id
);
3622 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id
, int *ret
) {
3625 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
3626 if (t
->tpm2_ecc_curve_id
== tpm2_ecc_curve_id
) {
3627 *ret
= t
->openssl_ecc_curve_id
;
3631 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3632 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id
);
3635 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
3637 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
3643 const TPMT_PUBLIC
*p
= &public->publicArea
;
3645 case TPM2_ALG_ECC
: {
3647 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
3651 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
3652 return ecc_pkey_from_curve_x_y(
3660 case TPM2_ALG_RSA
: {
3661 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
3662 * zero indicates that the exponent is the default of 2^16 + 1". */
3663 uint32_t exponent
= htobe32(p
->parameters
.rsaDetail
.exponent
?: TPM2_RSA_DEFAULT_EXPONENT
);
3664 return rsa_pkey_from_n_e(
3665 p
->unique
.rsa
.buffer
,
3672 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3673 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
3677 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY
*pkey
, TPM2B_PUBLIC
*ret
) {
3683 TPMT_PUBLIC
public = {
3684 .nameAlg
= TPM2_ALG_SHA256
,
3685 .objectAttributes
= TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
,
3686 .parameters
.asymDetail
= {
3687 .symmetric
.algorithm
= TPM2_ALG_NULL
,
3688 .scheme
.scheme
= TPM2_ALG_NULL
,
3692 #if OPENSSL_VERSION_MAJOR >= 3
3693 key_id
= EVP_PKEY_get_id(pkey
);
3695 key_id
= EVP_PKEY_id(pkey
);
3700 public.type
= TPM2_ALG_ECC
;
3703 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
3704 size_t x_size
, y_size
;
3705 r
= ecc_pkey_to_curve_x_y(pkey
, &curve_id
, &x
, &x_size
, &y
, &y_size
);
3707 return log_debug_errno(r
, "Could not get ECC key curve/x/y: %m");
3709 TPM2_ECC_CURVE curve
;
3710 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
3714 public.parameters
.eccDetail
.curveID
= curve
;
3716 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
3718 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
3720 return log_debug_errno(r
, "ECC key x size %zu too large.", x_size
);
3722 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
3724 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
3726 return log_debug_errno(r
, "ECC key y size %zu too large.", y_size
);
3728 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
3732 case EVP_PKEY_RSA
: {
3733 public.type
= TPM2_ALG_RSA
;
3735 _cleanup_free_
void *n
= NULL
, *e
= NULL
;
3736 size_t n_size
, e_size
;
3737 r
= rsa_pkey_to_n_e(pkey
, &n
, &n_size
, &e
, &e_size
);
3739 return log_debug_errno(r
, "Could not get RSA key n/e: %m");
3741 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
3743 return log_debug_errno(r
, "RSA key n size %zu too large.", n_size
);
3745 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
3746 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
3748 if (sizeof(uint32_t) < e_size
)
3749 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
3750 "RSA key e size %zu too large.", e_size
);
3752 uint32_t exponent
= 0;
3753 memcpy(&exponent
, e
, e_size
);
3754 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
3755 if (exponent
== TPM2_RSA_DEFAULT_EXPONENT
)
3757 public.parameters
.rsaDetail
.exponent
= exponent
;
3762 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3763 "EVP_PKEY type %d not supported.", key_id
);
3766 *ret
= (TPM2B_PUBLIC
) {
3767 .size
= sizeof(public),
3768 .publicArea
= public,
3775 int tpm2_tpm2b_public_to_fingerprint(
3776 const TPM2B_PUBLIC
*public,
3777 void **ret_fingerprint
,
3778 size_t *ret_fingerprint_size
) {
3784 assert(ret_fingerprint
);
3785 assert(ret_fingerprint_size
);
3787 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3788 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
3792 /* Hardcode fingerprint to SHA256 */
3793 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
3795 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3799 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
3806 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3807 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
3811 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
3813 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3817 /* Marshal the public and private objects into a single nonstandard 'blob'. This is not a (publicly) standard
3818 * format, this is specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
3819 * tpm2_unmarshal_blob(). */
3820 static int tpm2_marshal_blob(
3821 const TPM2B_PUBLIC
*public,
3822 const TPM2B_PRIVATE
*private,
3824 size_t *ret_blob_size
) {
3831 assert(ret_blob_size
);
3833 size_t max_size
= sizeof(*private) + sizeof(*public);
3835 _cleanup_free_
void *blob
= malloc(max_size
);
3837 return log_oom_debug();
3839 size_t blob_size
= 0;
3840 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
3841 if (rc
!= TSS2_RC_SUCCESS
)
3842 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3843 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
3845 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
3846 if (rc
!= TSS2_RC_SUCCESS
)
3847 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3848 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3850 *ret_blob
= TAKE_PTR(blob
);
3851 *ret_blob_size
= blob_size
;
3856 /* Unmarshal the 'blob' into public and private objects. This is not a (publicly) standard format, this is
3857 * specific to how we currently store the sealed object. This expects the 'blob' to have been created by
3858 * tpm2_marshal_blob(). */
3859 static int tpm2_unmarshal_blob(
3862 TPM2B_PUBLIC
*ret_public
,
3863 TPM2B_PRIVATE
*ret_private
) {
3869 assert(ret_private
);
3871 TPM2B_PRIVATE
private = {};
3873 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob
, blob_size
, &offset
, &private);
3874 if (rc
!= TSS2_RC_SUCCESS
)
3875 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3876 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
3878 TPM2B_PUBLIC
public = {};
3879 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob
, blob_size
, &offset
, &public);
3880 if (rc
!= TSS2_RC_SUCCESS
)
3881 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3882 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
3884 *ret_public
= public;
3885 *ret_private
= private;
3890 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
3891 * across restarts of the TPM or reboots (assuming the handle is persistent). */
3892 static int tpm2_serialize(
3894 const Tpm2Handle
*handle
,
3895 void **ret_serialized
,
3896 size_t *ret_serialized_size
) {
3902 assert(ret_serialized
);
3903 assert(ret_serialized_size
);
3905 _cleanup_(Esys_Freep
) unsigned char *serialized
= NULL
;
3907 rc
= sym_Esys_TR_Serialize(c
->esys_context
, handle
->esys_handle
, &serialized
, &size
);
3908 if (rc
!= TSS2_RC_SUCCESS
)
3909 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3910 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc
));
3912 *ret_serialized
= TAKE_PTR(serialized
);
3913 *ret_serialized_size
= size
;
3918 static int tpm2_deserialize(
3920 const void *serialized
,
3921 size_t serialized_size
,
3922 Tpm2Handle
**ret_handle
) {
3931 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
3932 r
= tpm2_handle_new(c
, &handle
);
3936 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
3937 handle
->flush
= false;
3939 rc
= sym_Esys_TR_Deserialize(c
->esys_context
, serialized
, serialized_size
, &handle
->esys_handle
);
3940 if (rc
!= TSS2_RC_SUCCESS
)
3941 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3942 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc
));
3944 *ret_handle
= TAKE_PTR(handle
);
3949 int tpm2_seal(Tpm2Context
*c
,
3950 uint32_t seal_key_handle
,
3951 const TPM2B_DIGEST
*policy
,
3954 size_t *ret_secret_size
,
3956 size_t *ret_blob_size
,
3957 uint16_t *ret_primary_alg
,
3959 size_t *ret_srk_buf_size
) {
3961 uint16_t primary_alg
= 0;
3965 assert(ret_secret_size
);
3967 assert(ret_blob_size
);
3969 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3970 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
3971 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3972 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3973 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3974 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3975 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3976 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3977 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3978 * LUKS2 JSON header.
3980 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3981 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3982 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3983 * binding the unlocking to the TPM2 chip. */
3985 usec_t start
= now(CLOCK_MONOTONIC
);
3987 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3988 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3989 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
3990 TPMT_PUBLIC hmac_template
= {
3991 .type
= TPM2_ALG_KEYEDHASH
,
3992 .nameAlg
= TPM2_ALG_SHA256
,
3993 .objectAttributes
= TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT
,
3994 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
3995 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
3996 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
3999 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
4000 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
4003 CLEANUP_ERASE(hmac_sensitive
);
4006 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
4011 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
4013 (void) tpm2_credit_random(c
);
4015 log_debug("Generating secret key data.");
4017 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
4019 return log_debug_errno(r
, "Failed to generate secret key: %m");
4021 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
4023 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
4025 if (IN_SET(seal_key_handle
, 0, TPM2_SRK_HANDLE
)) {
4026 r
= tpm2_get_or_create_srk(
4028 /* session= */ NULL
,
4030 /* ret_name= */ NULL
,
4031 /* ret_qname= */ NULL
,
4035 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle
), TPM2_HT_TRANSIENT
, TPM2_HT_PERSISTENT
)) {
4036 r
= tpm2_index_to_handle(
4039 /* session= */ NULL
,
4041 /* ret_name= */ NULL
,
4042 /* ret_qname= */ NULL
,
4047 /* We do NOT automatically create anything other than the SRK */
4048 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT
),
4049 "No handle found at index 0x%" PRIx32
, seal_key_handle
);
4051 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
4052 "Seal key handle 0x%" PRIx32
" is neither transient nor persistent.",
4055 primary_alg
= primary_public
->publicArea
.type
;
4057 if (seal_key_handle
!= 0)
4058 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
4060 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
4061 primary_alg
= TPM2_ALG_ECC
;
4063 TPM2B_PUBLIC
template = {
4064 .size
= sizeof(TPMT_PUBLIC
),
4066 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
4068 return log_debug_errno(r
, "Could not get legacy ECC template: %m");
4070 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
4071 primary_alg
= TPM2_ALG_RSA
;
4073 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
4075 return log_debug_errno(r
, "Could not get legacy RSA template: %m");
4077 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
))
4078 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4079 "TPM does not support either ECC or RSA legacy template.");
4082 r
= tpm2_create_primary(
4084 /* session= */ NULL
,
4086 /* sensitive= */ NULL
,
4087 /* ret_public= */ NULL
,
4093 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
4094 r
= tpm2_make_encryption_session(c
, primary_handle
, /* bind_key= */ NULL
, &encryption_session
);
4098 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
4099 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
4100 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
4104 _cleanup_(erase_and_freep
) void *secret
= NULL
;
4105 secret
= memdup(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
4107 return log_oom_debug();
4109 log_debug("Marshalling private and public part of HMAC key.");
4111 _cleanup_free_
void *blob
= NULL
;
4112 size_t blob_size
= 0;
4113 r
= tpm2_marshal_blob(public, private, &blob
, &blob_size
);
4115 return log_debug_errno(r
, "Could not create sealed blob: %m");
4118 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
4120 _cleanup_free_
void *srk_buf
= NULL
;
4121 size_t srk_buf_size
= 0;
4123 _cleanup_(Esys_Freep
) void *tmp
= NULL
;
4124 r
= tpm2_serialize(c
, primary_handle
, &tmp
, &srk_buf_size
);
4129 * make a copy since we don't want the caller to understand that
4130 * ESYS allocated the pointer. It would make tracking what deallocator
4131 * to use for srk_buf in which context a PITA.
4133 srk_buf
= memdup(tmp
, srk_buf_size
);
4135 return log_oom_debug();
4137 *ret_srk_buf
= TAKE_PTR(srk_buf
);
4138 *ret_srk_buf_size
= srk_buf_size
;
4141 *ret_secret
= TAKE_PTR(secret
);
4142 *ret_secret_size
= hmac_sensitive
.data
.size
;
4143 *ret_blob
= TAKE_PTR(blob
);
4144 *ret_blob_size
= blob_size
;
4146 if (ret_primary_alg
)
4147 *ret_primary_alg
= primary_alg
;
4152 #define RETRY_UNSEAL_MAX 30u
4154 int tpm2_unseal(Tpm2Context
*c
,
4155 uint32_t hash_pcr_mask
,
4159 uint32_t pubkey_pcr_mask
,
4160 JsonVariant
*signature
,
4162 uint16_t primary_alg
,
4165 const void *known_policy_hash
,
4166 size_t known_policy_hash_size
,
4167 const void *srk_buf
,
4168 size_t srk_buf_size
,
4170 size_t *ret_secret_size
) {
4176 assert(blob_size
> 0);
4177 assert(known_policy_hash_size
== 0 || known_policy_hash
);
4178 assert(pubkey_size
== 0 || pubkey
);
4180 assert(ret_secret_size
);
4182 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
4183 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
4185 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
4186 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
4187 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
4188 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
4189 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
4190 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
4191 * and use it to unlock the LUKS2 volume. */
4193 usec_t start
= now(CLOCK_MONOTONIC
);
4195 TPM2B_PUBLIC
public;
4196 TPM2B_PRIVATE
private;
4197 r
= tpm2_unmarshal_blob(blob
, blob_size
, &public, &private);
4199 return log_debug_errno(r
, "Could not extract parts from blob: %m");
4201 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
4202 * so we need to handle that legacy situation. */
4203 if (pcr_bank
== UINT16_MAX
) {
4204 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
4209 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
4211 r
= tpm2_deserialize(c
, srk_buf
, srk_buf_size
, &primary_handle
);
4214 } else if (primary_alg
!= 0) {
4215 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
4216 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
4218 return log_debug_errno(r
, "Could not get legacy template: %m");
4220 r
= tpm2_create_primary(
4222 /* session= */ NULL
,
4224 /* sensitive= */ NULL
,
4225 /* ret_public= */ NULL
,
4230 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
4231 "No SRK or primary alg provided.");
4233 log_debug("Loading HMAC key into TPM.");
4236 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
4237 * gives you back a different key, the session initiation will fail. In the
4238 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
4239 * provides protections.
4241 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
4242 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
4246 TPM2B_PUBLIC pubkey_tpm2b
;
4247 _cleanup_free_
void *fp
= NULL
;
4250 r
= tpm2_tpm2b_public_from_pem(pubkey
, pubkey_size
, &pubkey_tpm2b
);
4252 return log_debug_errno(r
, "Could not create TPMT_PUBLIC: %m");
4254 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
, &fp_size
);
4256 return log_debug_errno(r
, "Could not get key fingerprint: %m");
4260 * if a pin is set for the seal object, use it to bind the session
4261 * key to that object. This prevents active bus interposers from
4262 * faking a TPM and seeing the unsealed value. An active interposer
4263 * could fake a TPM, satisfying the encrypted session, and just
4264 * forward everything to the *real* TPM.
4266 r
= tpm2_set_auth(c
, hmac_key
, pin
);
4270 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
4271 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
4275 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
4276 for (unsigned i
= RETRY_UNSEAL_MAX
;; i
--) {
4277 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*policy_session
= NULL
;
4278 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
4279 r
= tpm2_make_policy_session(
4287 r
= tpm2_build_sealing_policy(
4292 pubkey
? &pubkey_tpm2b
: NULL
,
4301 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
4302 * wait until the TPM2 tells us to go away. */
4303 if (known_policy_hash_size
> 0 &&
4304 memcmp_nn(policy_digest
->buffer
, policy_digest
->size
, known_policy_hash
, known_policy_hash_size
) != 0)
4305 return log_debug_errno(SYNTHETIC_ERRNO(EPERM
),
4306 "Current policy digest does not match stored policy digest, cancelling "
4307 "TPM2 authentication attempt.");
4309 log_debug("Unsealing HMAC key.");
4311 rc
= sym_Esys_Unseal(
4313 hmac_key
->esys_handle
,
4314 policy_session
->esys_handle
,
4315 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
4318 if (rc
== TSS2_RC_SUCCESS
)
4320 if (rc
!= TPM2_RC_PCR_CHANGED
|| i
== 0)
4321 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4322 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc
));
4323 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i
);
4326 _cleanup_(erase_and_freep
) char *secret
= NULL
;
4327 secret
= memdup(unsealed
->buffer
, unsealed
->size
);
4328 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
4330 return log_oom_debug();
4333 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
4335 *ret_secret
= TAKE_PTR(secret
);
4336 *ret_secret_size
= unsealed
->size
;
4343 int tpm2_list_devices(void) {
4345 _cleanup_(table_unrefp
) Table
*t
= NULL
;
4346 _cleanup_closedir_
DIR *d
= NULL
;
4351 return log_error_errno(r
, "TPM2 support is not installed.");
4353 t
= table_new("path", "device", "driver");
4357 d
= opendir("/sys/class/tpmrm");
4359 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
4360 if (errno
!= ENOENT
)
4364 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
4367 de
= readdir_no_dot(d
);
4371 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
4375 r
= readlink_malloc(device_path
, &device
);
4377 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
4379 driver_path
= path_join(device_path
, "driver");
4383 r
= readlink_malloc(driver_path
, &driver
);
4385 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
4388 node
= path_join("/dev", de
->d_name
);
4395 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
4396 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
4398 return table_log_add_error(r
);
4402 if (table_get_rows(t
) <= 1) {
4403 log_info("No suitable TPM2 devices found.");
4407 r
= table_print(t
, stdout
);
4409 return log_error_errno(r
, "Failed to show device table: %m");
4413 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4414 "TPM2 not supported on this build.");
4418 int tpm2_find_device_auto(char **ret
) {
4420 _cleanup_closedir_
DIR *d
= NULL
;
4425 return log_debug_errno(r
, "TPM2 support is not installed.");
4427 d
= opendir("/sys/class/tpmrm");
4429 log_debug_errno(errno
, "Failed to open /sys/class/tpmrm: %m");
4430 if (errno
!= ENOENT
)
4433 _cleanup_free_
char *node
= NULL
;
4438 de
= readdir_no_dot(d
);
4443 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
4444 "More than one TPM2 (tpmrm) device found.");
4446 node
= path_join("/dev", de
->d_name
);
4448 return log_oom_debug();
4452 *ret
= TAKE_PTR(node
);
4457 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
4459 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4460 "TPM2 not supported on this build.");
4465 static const char* tpm2_userspace_event_type_table
[_TPM2_USERSPACE_EVENT_TYPE_MAX
] = {
4466 [TPM2_EVENT_PHASE
] = "phase",
4467 [TPM2_EVENT_FILESYSTEM
] = "filesystem",
4468 [TPM2_EVENT_VOLUME_KEY
] = "volume-key",
4469 [TPM2_EVENT_MACHINE_ID
] = "machine-id",
4472 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type
, Tpm2UserspaceEventType
);
4474 const char *tpm2_userspace_log_path(void) {
4475 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
4478 static int tpm2_userspace_log_open(void) {
4479 _cleanup_close_
int fd
= -EBADF
;
4484 e
= tpm2_userspace_log_path();
4485 (void) mkdir_parents(e
, 0755);
4487 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
4488 * because we use BSD file locking on it, and if anyone but root can access the file they can also
4489 * lock it, which we want to avoid. */
4490 fd
= open(e
, O_CREAT
|O_WRONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
, 0600);
4492 return log_debug_errno(errno
, "Failed to open TPM log file '%s' for writing, ignoring: %m", e
);
4494 if (flock(fd
, LOCK_EX
) < 0)
4495 return log_debug_errno(errno
, "Failed to lock TPM log file '%s', ignoring: %m", e
);
4497 if (fstat(fd
, &st
) < 0)
4498 return log_debug_errno(errno
, "Failed to fstat TPM log file '%s', ignoring: %m", e
);
4500 r
= stat_verify_regular(&st
);
4502 return log_debug_errno(r
, "TPM log file '%s' is not regular, ignoring: %m", e
);
4504 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
4505 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
4506 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
4507 * our assumed backend fs) doesn't know user xattrs. */
4508 if (st
.st_mode
& S_ISVTX
)
4509 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE
), "TPM log file '%s' aborted, ignoring.", e
);
4511 if (fchmod(fd
, 0600 | S_ISVTX
) < 0)
4512 return log_debug_errno(errno
, "Failed to chmod() TPM log file '%s', ignoring: %m", e
);
4517 static int tpm2_userspace_log(
4520 const TPML_DIGEST_VALUES
*values
,
4521 Tpm2UserspaceEventType event_type
,
4522 const char *description
) {
4524 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *array
= NULL
;
4525 _cleanup_free_
char *f
= NULL
;
4530 assert(values
->count
> 0);
4532 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
4533 * Format – the JSON flavour –
4534 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
4535 * ways from it, specifically:
4537 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
4538 * through the whole logs (include firmware logs) before knowing what the next value is we should
4539 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
4540 * it in when it uses the data.
4542 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
4543 * JSON array would mean that for each appending we'd have to read the whole log file fully into
4544 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
4545 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
4547 * It should be possible to convert this format in a relatively straight-forward way into the
4548 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
4549 * determined from the full dataset.
4551 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
4552 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
4553 * timestamp which can be used to order this measurement against possibly other measurements
4554 * independently done by other subsystems on the system.
4557 if (fd
< 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
4560 for (size_t i
= 0; i
< values
->count
; i
++) {
4561 const EVP_MD
*implementation
;
4564 assert_se(a
= tpm2_hash_alg_to_string(values
->digests
[i
].hashAlg
));
4565 assert_se(implementation
= EVP_get_digestbyname(a
));
4567 r
= json_variant_append_arrayb(
4568 &array
, JSON_BUILD_OBJECT(
4569 JSON_BUILD_PAIR_STRING("hashAlg", a
),
4570 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values
->digests
[i
].digest
, EVP_MD_size(implementation
)))));
4572 return log_debug_errno(r
, "Failed to append digest object to JSON array: %m");
4577 r
= sd_id128_get_boot(&boot_id
);
4579 return log_debug_errno(r
, "Failed to acquire boot ID: %m");
4581 r
= json_build(&v
, JSON_BUILD_OBJECT(
4582 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index
)),
4583 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array
)),
4584 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
4585 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
4586 JSON_BUILD_PAIR_CONDITION(description
, "string", JSON_BUILD_STRING(description
)),
4587 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id
)),
4588 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME
))),
4589 JSON_BUILD_PAIR_CONDITION(event_type
>= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type
)))))));
4591 return log_debug_errno(r
, "Failed to build log record JSON: %m");
4593 r
= json_variant_format(v
, JSON_FORMAT_SEQ
, &f
);
4595 return log_debug_errno(r
, "Failed to format JSON: %m");
4597 if (lseek(fd
, 0, SEEK_END
) < 0)
4598 return log_debug_errno(errno
, "Failed to seek to end of JSON log: %m");
4600 r
= loop_write(fd
, f
, SIZE_MAX
);
4602 return log_debug_errno(r
, "Failed to write JSON data to log: %m");
4605 return log_debug_errno(errno
, "Failed to sync JSON data: %m");
4607 /* Unset S_ISVTX again */
4608 if (fchmod(fd
, 0600) < 0)
4609 return log_debug_errno(errno
, "Failed to chmod() TPM log file, ignoring: %m");
4613 return log_debug_errno(r
, "Failed to sync JSON log: %m");
4618 int tpm2_extend_bytes(
4626 Tpm2UserspaceEventType event_type
,
4627 const char *description
) {
4630 _cleanup_close_
int log_fd
= -EBADF
;
4631 TPML_DIGEST_VALUES values
= {};
4635 assert(data
|| data_size
== 0);
4636 assert(secret
|| secret_size
== 0);
4638 if (data_size
== SIZE_MAX
)
4639 data_size
= strlen(data
);
4640 if (secret_size
== SIZE_MAX
)
4641 secret_size
= strlen(secret
);
4643 if (pcr_index
>= TPM2_PCRS_MAX
)
4644 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Can't measure into unsupported PCR %u, refusing.", pcr_index
);
4646 if (strv_isempty(banks
))
4649 STRV_FOREACH(bank
, banks
) {
4650 const EVP_MD
*implementation
;
4653 assert_se(implementation
= EVP_get_digestbyname(*bank
));
4655 if (values
.count
>= ELEMENTSOF(values
.digests
))
4656 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
4658 if ((size_t) EVP_MD_size(implementation
) > sizeof(values
.digests
[values
.count
].digest
))
4659 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Hash result too large for TPM2.");
4661 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
4663 return log_debug_errno(id
, "Can't map hash name to TPM2.");
4665 values
.digests
[values
.count
].hashAlg
= id
;
4667 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
4668 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
4669 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
4670 * secret for other purposes, maybe because it needs a shorter secret derived from it for
4671 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
4672 * private non-secret string instead. */
4673 if (secret_size
> 0) {
4674 if (!HMAC(implementation
, secret
, secret_size
, data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
))
4675 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to calculate HMAC of data to measure.");
4676 } else if (EVP_Digest(data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
, implementation
, NULL
) != 1)
4677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to hash data to measure.");
4682 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
4683 * and our measurement and change either */
4684 log_fd
= tpm2_userspace_log_open();
4686 rc
= sym_Esys_PCR_Extend(
4688 ESYS_TR_PCR0
+ pcr_index
,
4693 if (rc
!= TSS2_RC_SUCCESS
)
4694 return log_debug_errno(
4695 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4696 "Failed to measure into PCR %u: %s",
4698 sym_Tss2_RC_Decode(rc
));
4700 /* Now, write what we just extended to the log, too. */
4701 (void) tpm2_userspace_log(log_fd
, pcr_index
, &values
, event_type
, description
);
4704 #else /* HAVE_OPENSSL */
4705 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4710 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
4711 _cleanup_free_
char *s
= NULL
;
4713 FOREACH_PCR_IN_MASK(n
, mask
)
4714 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
4723 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
4724 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
4729 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
4730 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
4732 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
4735 r
= json_variant_new_integer(&e
, i
);
4739 r
= json_variant_append_array(&a
, e
);
4745 return json_variant_new_array(ret
, NULL
, 0);
4751 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
4755 if (!json_variant_is_array(v
))
4756 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
4758 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
4761 if (!json_variant_is_unsigned(e
))
4762 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
4764 u
= json_variant_unsigned(e
);
4765 if (u
>= TPM2_PCRS_MAX
)
4766 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR number out of range: %" PRIu64
, u
);
4768 mask
|= UINT32_C(1) << u
;
4777 int tpm2_make_luks2_json(
4779 uint32_t hash_pcr_mask
,
4783 uint32_t pubkey_pcr_mask
,
4784 uint16_t primary_alg
,
4787 const void *policy_hash
,
4788 size_t policy_hash_size
,
4791 const void *srk_buf
,
4792 size_t srk_buf_size
,
4794 JsonVariant
**ret
) {
4796 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
4797 _cleanup_free_
char *keyslot_as_string
= NULL
;
4800 assert(blob
|| blob_size
== 0);
4801 assert(policy_hash
|| policy_hash_size
== 0);
4802 assert(pubkey
|| pubkey_size
== 0);
4804 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
4807 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
4811 if (pubkey_pcr_mask
!= 0) {
4812 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
4817 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
4818 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
4819 * object should use "_" rather than "-" in field names. */
4823 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
4824 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string
))),
4825 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob
, blob_size
)),
4826 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj
)),
4827 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank
), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank
))),
4828 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg
), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg
))),
4829 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash
, policy_hash_size
)),
4830 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags
& TPM2_FLAGS_USE_PIN
)),
4831 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj
)),
4832 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey
, pubkey_size
)),
4833 JSON_BUILD_PAIR_CONDITION(salt
, "tpm2_salt", JSON_BUILD_BASE64(salt
, salt_size
)),
4834 JSON_BUILD_PAIR_CONDITION(srk_buf
, "tpm2_srk", JSON_BUILD_BASE64(srk_buf
, srk_buf_size
))));
4844 int tpm2_parse_luks2_json(
4847 uint32_t *ret_hash_pcr_mask
,
4848 uint16_t *ret_pcr_bank
,
4850 size_t *ret_pubkey_size
,
4851 uint32_t *ret_pubkey_pcr_mask
,
4852 uint16_t *ret_primary_alg
,
4854 size_t *ret_blob_size
,
4855 void **ret_policy_hash
,
4856 size_t *ret_policy_hash_size
,
4858 size_t *ret_salt_size
,
4860 size_t *ret_srk_buf_size
,
4861 TPM2Flags
*ret_flags
) {
4863 _cleanup_free_
void *blob
= NULL
, *policy_hash
= NULL
, *pubkey
= NULL
, *salt
= NULL
, *srk_buf
= NULL
;
4864 size_t blob_size
= 0, policy_hash_size
= 0, pubkey_size
= 0, salt_size
= 0, srk_buf_size
= 0;
4865 uint32_t hash_pcr_mask
= 0, pubkey_pcr_mask
= 0;
4866 uint16_t primary_alg
= TPM2_ALG_ECC
; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
4867 uint16_t pcr_bank
= UINT16_MAX
; /* default: pick automatically */
4868 int r
, keyslot
= -1;
4869 TPM2Flags flags
= 0;
4875 keyslot
= cryptsetup_get_keyslot_from_token(v
);
4877 /* Return a recognizable error when parsing this field, so that callers can handle parsing
4878 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
4880 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4885 w
= json_variant_by_key(v
, "tpm2-pcrs");
4887 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
4889 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
4891 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
4893 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4895 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
4897 /* The PCR bank field is optional */
4899 if (!json_variant_is_string(w
))
4900 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
4902 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
4904 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
4909 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4910 * the algorithm was hardcoded to ECC. */
4911 w
= json_variant_by_key(v
, "tpm2-primary-alg");
4913 /* The primary key algorithm is optional */
4915 if (!json_variant_is_string(w
))
4916 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
4918 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
4920 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
4925 w
= json_variant_by_key(v
, "tpm2-blob");
4927 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
4929 r
= json_variant_unbase64(w
, &blob
, &blob_size
);
4931 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
4933 w
= json_variant_by_key(v
, "tpm2-policy-hash");
4935 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4937 r
= json_variant_unhex(w
, &policy_hash
, &policy_hash_size
);
4939 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
4941 w
= json_variant_by_key(v
, "tpm2-pin");
4943 if (!json_variant_is_boolean(w
))
4944 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
4946 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
4949 w
= json_variant_by_key(v
, "tpm2_salt");
4951 r
= json_variant_unbase64(w
, &salt
, &salt_size
);
4953 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
4956 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
4958 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
4963 w
= json_variant_by_key(v
, "tpm2_pubkey");
4965 r
= json_variant_unbase64(w
, &pubkey
, &pubkey_size
);
4967 return log_debug_errno(r
, "Failed to decode PCR public key.");
4968 } else if (pubkey_pcr_mask
!= 0)
4969 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4971 w
= json_variant_by_key(v
, "tpm2_srk");
4973 r
= json_variant_unbase64(w
, &srk_buf
, &srk_buf_size
);
4975 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
4979 *ret_keyslot
= keyslot
;
4980 if (ret_hash_pcr_mask
)
4981 *ret_hash_pcr_mask
= hash_pcr_mask
;
4983 *ret_pcr_bank
= pcr_bank
;
4985 *ret_pubkey
= TAKE_PTR(pubkey
);
4986 if (ret_pubkey_size
)
4987 *ret_pubkey_size
= pubkey_size
;
4988 if (ret_pubkey_pcr_mask
)
4989 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
4990 if (ret_primary_alg
)
4991 *ret_primary_alg
= primary_alg
;
4993 *ret_blob
= TAKE_PTR(blob
);
4995 *ret_blob_size
= blob_size
;
4996 if (ret_policy_hash
)
4997 *ret_policy_hash
= TAKE_PTR(policy_hash
);
4998 if (ret_policy_hash_size
)
4999 *ret_policy_hash_size
= policy_hash_size
;
5001 *ret_salt
= TAKE_PTR(salt
);
5003 *ret_salt_size
= salt_size
;
5007 *ret_srk_buf
= TAKE_PTR(srk_buf
);
5008 if (ret_srk_buf_size
)
5009 *ret_srk_buf_size
= srk_buf_size
;
5014 int tpm2_hash_alg_to_size(uint16_t alg
) {
5018 case TPM2_ALG_SHA256
:
5020 case TPM2_ALG_SHA384
:
5022 case TPM2_ALG_SHA512
:
5025 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
5029 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
5033 case TPM2_ALG_SHA256
:
5035 case TPM2_ALG_SHA384
:
5037 case TPM2_ALG_SHA512
:
5040 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
5045 int tpm2_hash_alg_from_string(const char *alg
) {
5046 if (strcaseeq_ptr(alg
, "sha1"))
5047 return TPM2_ALG_SHA1
;
5048 if (strcaseeq_ptr(alg
, "sha256"))
5049 return TPM2_ALG_SHA256
;
5050 if (strcaseeq_ptr(alg
, "sha384"))
5051 return TPM2_ALG_SHA384
;
5052 if (strcaseeq_ptr(alg
, "sha512"))
5053 return TPM2_ALG_SHA512
;
5054 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm name '%s'", alg
);
5057 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
5064 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
5069 int tpm2_asym_alg_from_string(const char *alg
) {
5070 if (strcaseeq_ptr(alg
, "ecc"))
5071 return TPM2_ALG_ECC
;
5072 if (strcaseeq_ptr(alg
, "rsa"))
5073 return TPM2_ALG_RSA
;
5074 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown asymmetric algorithm name '%s'", alg
);
5077 Tpm2Support
tpm2_support(void) {
5078 Tpm2Support support
= TPM2_SUPPORT_NONE
;
5081 if (detect_container() <= 0) {
5082 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
5083 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
5084 * let's assume containers never have a TPM, at least for now. */
5086 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
5089 log_debug_errno(r
, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
5090 } else if (r
== 0) /* populated! */
5091 support
|= TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_DRIVER
;
5093 /* If the directory exists but is empty, we know the subsystem is enabled but no
5094 * driver has been loaded yet. */
5095 support
|= TPM2_SUPPORT_SUBSYSTEM
;
5099 support
|= TPM2_SUPPORT_FIRMWARE
;
5102 support
|= TPM2_SUPPORT_SYSTEM
;
5106 support
|= TPM2_SUPPORT_LIBRARIES
;
5113 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
5114 TPMI_ALG_HASH default_hash
= 0;
5115 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
5117 default_hash
= v
->hash
;
5121 if (default_hash
!= 0)
5122 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
5124 v
->hash
= default_hash
;
5128 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
5129 * parse_*_argument() functions. */
5131 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
5133 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
5134 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
5135 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
5137 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
5138 * tpm2_parse_pcr_argument_append(). */
5139 int tpm2_parse_pcr_argument(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
5144 assert(ret_pcr_values
);
5145 assert(ret_n_pcr_values
);
5147 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
5148 size_t n_pcr_values
= 0;
5149 r
= tpm2_pcr_values_from_string(arg
, &pcr_values
, &n_pcr_values
);
5151 return log_error_errno(r
, "Could not parse PCR values from '%s': %m", arg
);
5153 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
5155 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
5157 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
5158 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
5160 *ret_pcr_values
= TAKE_PTR(pcr_values
);
5161 *ret_n_pcr_values
= n_pcr_values
;
5165 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
5169 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
5170 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
5173 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
5174 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
5175 * algorithm check applied again (in case either the previous or current array had no default hash
5176 * algorithm), and then the resulting array is sorted and rechecked for validity. */
5177 int tpm2_parse_pcr_argument_append(const char *arg
, Tpm2PCRValue
**pcr_values
, size_t *n_pcr_values
) {
5183 assert(n_pcr_values
);
5185 _cleanup_free_ Tpm2PCRValue
*more_pcr_values
= NULL
;
5186 size_t n_more_pcr_values
;
5187 r
= tpm2_parse_pcr_argument(arg
, &more_pcr_values
, &n_more_pcr_values
);
5191 /* If we got previous values, append them. */
5192 if (*pcr_values
&& !GREEDY_REALLOC_APPEND(more_pcr_values
, n_more_pcr_values
, *pcr_values
, *n_pcr_values
))
5195 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values
, n_more_pcr_values
);
5197 tpm2_sort_pcr_values(more_pcr_values
, n_more_pcr_values
);
5199 if (!tpm2_pcr_values_valid(more_pcr_values
, n_more_pcr_values
))
5200 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
5202 SWAP_TWO(*pcr_values
, more_pcr_values
);
5203 *n_pcr_values
= n_more_pcr_values
;
5207 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
5211 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
5212 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
5213 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
5214 * UINT32_MAX, and or-ing the mask otherwise. */
5215 int tpm2_parse_pcr_argument_to_mask(const char *arg
, uint32_t *ret_mask
) {
5217 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
5218 size_t n_pcr_values
;
5224 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
5228 if (n_pcr_values
== 0) {
5229 /* This retains the previous behavior of clearing the mask if the arg is empty */
5235 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
5237 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
5240 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
5243 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
5245 return log_error_errno(r
, "Could not get pcr values mask: %m");
5247 if (*ret_mask
== UINT32_MAX
)
5248 *ret_mask
= new_mask
;
5250 *ret_mask
|= new_mask
;
5254 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
5258 int tpm2_load_pcr_signature(const char *path
, JsonVariant
**ret
) {
5259 _cleanup_strv_free_
char **search
= NULL
;
5260 _cleanup_free_
char *discovered_path
= NULL
;
5261 _cleanup_fclose_
FILE *f
= NULL
;
5264 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
5265 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5267 search
= strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
5269 return log_oom_debug();
5272 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
5273 * this case include /.extra/ in the search path, but only in this case, and if we run in the
5274 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
5276 path
= "tpm2-pcr-signature.json";
5279 if (strv_extend(&search
, "/.extra") < 0)
5280 return log_oom_debug();
5283 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
5285 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
5287 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
5289 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
5294 int tpm2_load_pcr_public_key(const char *path
, void **ret_pubkey
, size_t *ret_pubkey_size
) {
5295 _cleanup_free_
char *discovered_path
= NULL
;
5296 _cleanup_fclose_
FILE *f
= NULL
;
5299 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
5300 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5303 path
= "tpm2-pcr-public-key.pem";
5305 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
5307 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
5309 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
5311 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
5316 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
5319 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
5320 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
5321 * I found the wikipedia entry relevant and it contains links to
5323 * - https://en.wikipedia.org/wiki/PBKDF2
5324 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
5326 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
5330 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
5332 uint8_t _cleanup_(erase_and_freep
) *buffer
= NULL
;
5333 uint8_t u
[SHA256_DIGEST_SIZE
];
5335 /* To keep this simple, since derived KeyLen (dkLen in docs)
5336 * Is the same as the hash output, we don't need multiple
5337 * blocks. Part of the algorithm is to add the block count
5338 * in, but this can be hardcoded to 1.
5340 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
5343 assert (saltlen
> 0);
5344 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
5345 assert (passlen
> 0);
5348 * Build a buffer of salt + block_cnt and hmac_sha256 it we
5349 * do this as we don't have a context builder for HMAC_SHA256.
5351 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
5355 memcpy(buffer
, salt
, saltlen
);
5356 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
5358 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
5360 /* dk needs to be an unmodified u as u gets modified in the loop */
5361 memcpy(ret_key
, u
, SHA256_DIGEST_SIZE
);
5362 uint8_t *dk
= ret_key
;
5364 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
5365 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
5367 for (size_t j
=0; j
< sizeof(u
); j
++)
5374 static const char* const tpm2_pcr_index_table
[_TPM2_PCR_INDEX_MAX_DEFINED
] = {
5375 [TPM2_PCR_PLATFORM_CODE
] = "platform-code",
5376 [TPM2_PCR_PLATFORM_CONFIG
] = "platform-config",
5377 [TPM2_PCR_EXTERNAL_CODE
] = "external-code",
5378 [TPM2_PCR_EXTERNAL_CONFIG
] = "external-config",
5379 [TPM2_PCR_BOOT_LOADER_CODE
] = "boot-loader-code",
5380 [TPM2_PCR_BOOT_LOADER_CONFIG
] = "boot-loader-config",
5381 [TPM2_PCR_HOST_PLATFORM
] = "host-platform",
5382 [TPM2_PCR_SECURE_BOOT_POLICY
] = "secure-boot-policy",
5383 [TPM2_PCR_KERNEL_INITRD
] = "kernel-initrd",
5384 [TPM2_PCR_IMA
] = "ima",
5385 [TPM2_PCR_KERNEL_BOOT
] = "kernel-boot",
5386 [TPM2_PCR_KERNEL_CONFIG
] = "kernel-config",
5387 [TPM2_PCR_SYSEXTS
] = "sysexts",
5388 [TPM2_PCR_SHIM_POLICY
] = "shim-policy",
5389 [TPM2_PCR_SYSTEM_IDENTITY
] = "system-identity",
5390 [TPM2_PCR_DEBUG
] = "debug",
5391 [TPM2_PCR_APPLICATION_SUPPORT
] = "application-support",
5394 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index
, int, TPM2_PCRS_MAX
- 1);
5395 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index
, int);