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_Serialize
)(ESYS_CONTEXT
*esys_context
, ESYS_TR object
, uint8_t **buffer
, size_t *buffer_size
) = NULL
;
69 static TSS2_RC (*sym_Esys_TR_SetAuth
)(ESYS_CONTEXT
*esysContext
, ESYS_TR handle
, TPM2B_AUTH
const *authValue
) = NULL
;
70 static TSS2_RC (*sym_Esys_TRSess_GetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION
*flags
) = NULL
;
71 static TSS2_RC (*sym_Esys_TRSess_SetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION flags
, TPMA_SESSION mask
) = NULL
;
72 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
;
73 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
;
75 static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal
)(TPM2_CC src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
76 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal
)(TPM2B_PRIVATE
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
77 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PRIVATE
*dest
) = NULL
;
78 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal
)(TPM2B_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
79 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PUBLIC
*dest
) = NULL
;
80 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
;
81 static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal
)(TPMT_HA
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
82 static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal
)(TPMT_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
84 static const char* (*sym_Tss2_RC_Decode
)(TSS2_RC rc
) = NULL
;
86 int dlopen_tpm2(void) {
89 r
= dlopen_many_sym_or_warn(
90 &libtss2_esys_dl
, "libtss2-esys.so.0", LOG_DEBUG
,
91 DLSYM_ARG(Esys_Create
),
92 DLSYM_ARG(Esys_CreateLoaded
),
93 DLSYM_ARG(Esys_CreatePrimary
),
94 DLSYM_ARG(Esys_EvictControl
),
95 DLSYM_ARG(Esys_Finalize
),
96 DLSYM_ARG(Esys_FlushContext
),
98 DLSYM_ARG(Esys_GetCapability
),
99 DLSYM_ARG(Esys_GetRandom
),
100 DLSYM_ARG(Esys_Initialize
),
101 DLSYM_ARG(Esys_Load
),
102 DLSYM_ARG(Esys_LoadExternal
),
103 DLSYM_ARG(Esys_PCR_Extend
),
104 DLSYM_ARG(Esys_PCR_Read
),
105 DLSYM_ARG(Esys_PolicyAuthorize
),
106 DLSYM_ARG(Esys_PolicyAuthValue
),
107 DLSYM_ARG(Esys_PolicyGetDigest
),
108 DLSYM_ARG(Esys_PolicyPCR
),
109 DLSYM_ARG(Esys_ReadPublic
),
110 DLSYM_ARG(Esys_StartAuthSession
),
111 DLSYM_ARG(Esys_Startup
),
112 DLSYM_ARG(Esys_TestParms
),
113 DLSYM_ARG(Esys_TR_Close
),
114 DLSYM_ARG(Esys_TR_Deserialize
),
115 DLSYM_ARG(Esys_TR_FromTPMPublic
),
116 DLSYM_ARG(Esys_TR_GetName
),
117 DLSYM_ARG(Esys_TR_Serialize
),
118 DLSYM_ARG(Esys_TR_SetAuth
),
119 DLSYM_ARG(Esys_TRSess_GetAttributes
),
120 DLSYM_ARG(Esys_TRSess_SetAttributes
),
121 DLSYM_ARG(Esys_Unseal
),
122 DLSYM_ARG(Esys_VerifySignature
));
126 r
= dlopen_many_sym_or_warn(
127 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
128 DLSYM_ARG(Tss2_RC_Decode
));
132 return dlopen_many_sym_or_warn(
133 &libtss2_mu_dl
, "libtss2-mu.so.0", LOG_DEBUG
,
134 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal
),
135 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal
),
136 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal
),
137 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal
),
138 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal
),
139 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal
),
140 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal
),
141 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal
));
144 static void Esys_Freep(void *p
) {
146 sym_Esys_Free(*(void**) p
);
149 /* Get a specific TPM capability (or capabilities).
151 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
152 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
153 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
154 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
156 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
157 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
158 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
159 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
160 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
161 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
162 * capability category may have more specific requirements than described here; see the spec for exact
164 static int tpm2_get_capability(
169 TPMU_CAPABILITIES
*ret_capability_data
) {
171 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
177 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
178 capability
, property
, count
);
180 rc
= sym_Esys_GetCapability(
190 if (rc
!= TSS2_RC_SUCCESS
)
191 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
192 "Failed to get TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
": %s",
193 capability
, property
, sym_Tss2_RC_Decode(rc
));
195 if (capabilities
->capability
!= capability
)
196 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
197 "TPM provided wrong capability: 0x%04" PRIx32
" instead of 0x%04" PRIx32
".",
198 capabilities
->capability
, capability
);
200 if (ret_capability_data
)
201 *ret_capability_data
= capabilities
->data
;
203 return more
== TPM2_YES
;
206 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
208 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
209 TPMU_CAPABILITIES capability
;
214 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
215 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
216 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
217 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
218 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
219 * changed while we are performing some operation, it's reasonable to assume it will break us even if
220 * we don't cache the algorithms, thus they should be "safe" to cache. */
221 TPM2_ALG_ID current_alg
= TPM2_ALG_FIRST
;
223 r
= tpm2_get_capability(
226 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
232 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
234 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
235 * there are no more. */
236 assert(algorithms
.count
> 0);
238 if (!GREEDY_REALLOC_APPEND(
239 c
->capability_algorithms
,
240 c
->n_capability_algorithms
,
241 algorithms
.algProperties
,
248 /* Set current_alg to alg id after last alg id the TPM provided */
249 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
252 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
253 * while running, but that would be crazy, so let's hope it is not possible. */
254 TPM2_CC current_cc
= TPM2_CC_FIRST
;
256 r
= tpm2_get_capability(
265 TPML_CCA commands
= capability
.command
;
267 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
268 * there are no more. */
269 assert(commands
.count
> 0);
271 if (!GREEDY_REALLOC_APPEND(
272 c
->capability_commands
,
273 c
->n_capability_commands
,
274 commands
.commandAttributes
,
281 /* Set current_cc to index after last cc the TPM provided */
282 current_cc
= TPMA_CC_TO_TPM2_CC(commands
.commandAttributes
[commands
.count
- 1]) + 1;
285 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
286 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
287 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
288 * safely assume the TPM PCR allocation will not change while we are using it. */
289 r
= tpm2_get_capability(
298 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
299 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
300 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
301 * this command with the full PCR allocation and moreData will be NO." */
302 log_warning("TPM bug: reported multiple PCR sets; using only first set.");
303 c
->capability_pcrs
= capability
.assignedPCR
;
308 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
309 * TPMA_ALGORITHM is provided, otherwise false. */
310 static bool tpm2_get_capability_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
, TPMA_ALGORITHM
*ret
) {
313 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
314 if (alg_prop
->alg
== alg
) {
316 *ret
= alg_prop
->algProperties
;
320 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
327 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
328 return tpm2_get_capability_alg(c
, alg
, NULL
);
331 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
332 * otherwise false. */
333 static bool tpm2_get_capability_command(Tpm2Context
*c
, TPM2_CC command
, TPMA_CC
*ret
) {
336 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
337 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
343 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
350 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
351 return tpm2_get_capability_command(c
, command
, NULL
);
354 /* Returns 1 if the TPM supports the ECC curve, 0 if not, or < 0 for any error. */
355 static int tpm2_supports_ecc_curve(Tpm2Context
*c
, TPM2_ECC_CURVE curve
) {
356 TPMU_CAPABILITIES capability
;
359 /* The spec explicitly states the TPM2_ECC_CURVE should be cast to uint32_t. */
360 r
= tpm2_get_capability(c
, TPM2_CAP_ECC_CURVES
, (uint32_t) curve
, 1, &capability
);
364 TPML_ECC_CURVE eccCurves
= capability
.eccCurves
;
365 if (eccCurves
.count
== 0 || eccCurves
.eccCurves
[0] != curve
) {
366 log_debug("TPM does not support ECC curve 0x%02" PRIx16
".", curve
);
373 /* Query the TPM for populated handles.
375 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
376 * contain only populated handle addresses (which might not include the requested handle). The number of
377 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
378 * range (i.e. handle & 0xff000000).
380 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
381 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
382 static int tpm2_get_capability_handles(
386 TPM2_HANDLE
**ret_handles
,
387 size_t *ret_n_handles
) {
389 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
390 size_t n_handles
= 0;
391 TPM2_HANDLE current
= start
;
396 assert(ret_n_handles
);
399 TPMU_CAPABILITIES capability
;
400 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
404 TPML_HANDLE handle_list
= capability
.handles
;
405 if (handle_list
.count
== 0)
408 assert(handle_list
.count
<= max
);
410 if (n_handles
> SIZE_MAX
- handle_list
.count
)
413 if (!GREEDY_REALLOC(handles
, n_handles
+ handle_list
.count
))
416 memcpy_safe(&handles
[n_handles
], handle_list
.handle
, sizeof(handles
[0]) * handle_list
.count
);
418 max
-= handle_list
.count
;
419 n_handles
+= handle_list
.count
;
421 /* Update current to the handle index after the last handle in the list. */
422 current
= handles
[n_handles
- 1] + 1;
425 /* No more handles in this range. */
429 *ret_handles
= TAKE_PTR(handles
);
430 *ret_n_handles
= n_handles
;
435 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
436 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
438 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
439 static int tpm2_get_capability_handle(Tpm2Context
*c
, TPM2_HANDLE handle
) {
440 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
441 size_t n_handles
= 0;
444 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
448 return n_handles
== 0 ? false : handles
[0] == handle
;
451 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
452 bool tpm2_test_parms(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, const TPMU_PUBLIC_PARMS
*parms
) {
458 TPMT_PUBLIC_PARMS parameters
= {
460 .parameters
= *parms
,
463 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
464 if (rc
!= TSS2_RC_SUCCESS
)
465 /* The spec says if the parms are not supported the TPM returns "...the appropriate
466 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
467 * unmarshaling errors, instead of checking for them all here, let's just assume any error
468 * indicates unsupported parms, and log the specific error text. */
469 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc
));
471 return rc
== TSS2_RC_SUCCESS
;
474 static bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
478 return tpm2_test_parms(c
, public->type
, &public->parameters
);
481 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
485 TPMU_PUBLIC_PARMS parms
= {
486 .symDetail
.sym
= *parameters
,
489 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
492 static bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
496 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
497 * functionally identical. */
498 TPMT_SYM_DEF_OBJECT object
= {
499 .algorithm
= parameters
->algorithm
,
500 .keyBits
= parameters
->keyBits
,
501 .mode
= parameters
->mode
,
504 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
507 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
512 sym_Esys_Finalize(&c
->esys_context
);
514 c
->tcti_context
= mfree(c
->tcti_context
);
515 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
517 c
->capability_algorithms
= mfree(c
->capability_algorithms
);
518 c
->capability_commands
= mfree(c
->capability_commands
);
523 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
525 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
526 .algorithm
= TPM2_ALG_AES
,
528 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
531 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
532 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
538 context
= new(Tpm2Context
, 1);
542 *context
= (Tpm2Context
) {
548 return log_error_errno(r
, "TPM2 support not installed: %m");
551 device
= secure_getenv("SYSTEMD_TPM2_DEVICE");
553 /* Setting the env var to an empty string forces tpm2-tss' own device picking
554 * logic to be used. */
555 device
= empty_to_null(device
);
557 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
558 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
559 * might be used and we really don't want that, since it is a system service and that creates
560 * various ordering issues/deadlocks during early boot. */
561 device
= "device:/dev/tpmrm0";
565 const char *param
, *driver
, *fn
;
566 const TSS2_TCTI_INFO
* info
;
567 TSS2_TCTI_INFO_FUNC func
;
570 param
= strchr(device
, ':');
572 /* Syntax #1: Pair of driver string and arbitrary parameter */
573 driver
= strndupa_safe(device
, param
- device
);
575 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
578 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
579 /* Syntax #2: TPM device node */
583 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
585 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
587 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
589 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
590 if (!filename_is_valid(fn
))
591 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name '%s' not valid, refusing.", driver
);
593 context
->tcti_dl
= dlopen(fn
, RTLD_NOW
);
594 if (!context
->tcti_dl
)
595 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to load %s: %s", fn
, dlerror());
597 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
599 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
600 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
605 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
607 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
609 rc
= info
->init(NULL
, &sz
, NULL
);
610 if (rc
!= TPM2_RC_SUCCESS
)
611 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
612 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
614 context
->tcti_context
= malloc0(sz
);
615 if (!context
->tcti_context
)
618 rc
= info
->init(context
->tcti_context
, &sz
, param
);
619 if (rc
!= TPM2_RC_SUCCESS
)
620 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
621 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
624 rc
= sym_Esys_Initialize(&context
->esys_context
, context
->tcti_context
, NULL
);
625 if (rc
!= TSS2_RC_SUCCESS
)
626 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
627 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc
));
629 rc
= sym_Esys_Startup(context
->esys_context
, TPM2_SU_CLEAR
);
630 if (rc
== TPM2_RC_INITIALIZE
)
631 log_debug("TPM already started up.");
632 else if (rc
== TSS2_RC_SUCCESS
)
633 log_debug("TPM successfully started up.");
635 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
636 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
638 r
= tpm2_cache_capabilities(context
);
642 /* We require AES and CFB support for session encryption. */
643 if (!tpm2_supports_alg(context
, TPM2_ALG_AES
))
644 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES.");
646 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
647 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support CFB.");
649 if (!tpm2_supports_tpmt_sym_def(context
, &SESSION_TEMPLATE_SYM_AES_128_CFB
))
650 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES-128-CFB.");
652 *ret_context
= TAKE_PTR(context
);
657 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
660 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
663 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
664 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
665 * as removing its corresponding handle from the actual TPM. */
667 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
669 rc
= sym_Esys_TR_Close(esys_context
, &esys_handle
);
670 if (rc
!= TSS2_RC_SUCCESS
) /* We ignore failures here (besides debug logging), since this is called
671 * in error paths, where we cannot do anything about failures anymore. And
672 * when it is called in successful codepaths by this time we already did
673 * what we wanted to do, and got the results we wanted so there's no
674 * reason to make this fail more loudly than necessary. */
675 log_debug("Failed to %s TPM handle, ignoring: %s", flush
? "flush" : "close", sym_Tss2_RC_Decode(rc
));
678 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
682 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
684 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
686 return mfree(handle
);
689 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
690 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
694 handle
= new(Tpm2Handle
, 1);
698 *handle
= (Tpm2Handle
) {
699 .tpm2_context
= tpm2_context_ref(context
),
700 .esys_handle
= ESYS_TR_NONE
,
704 *ret_handle
= TAKE_PTR(handle
);
709 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the TPM2_HANDLE address
710 * provided. This should be used only for persistent, transient, or NV handles. Returns 1 on success, 0 if
711 * the requested handle is not present in the TPM, or < 0 on error. */
712 static int tpm2_esys_handle_from_tpm_handle(
714 const Tpm2Handle
*session
,
715 TPM2_HANDLE tpm_handle
,
716 Tpm2Handle
**ret_handle
) {
722 assert(tpm_handle
> 0);
725 /* Let's restrict this, at least for now, to allow only some handle types. */
726 switch (TPM2_HANDLE_TYPE(tpm_handle
)) {
727 case TPM2_HT_PERSISTENT
:
728 case TPM2_HT_NV_INDEX
:
729 case TPM2_HT_TRANSIENT
:
732 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
733 "Refusing to create ESYS handle for PCR handle 0x%08" PRIx32
".",
735 case TPM2_HT_HMAC_SESSION
:
736 case TPM2_HT_POLICY_SESSION
:
737 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
738 "Refusing to create ESYS handle for session handle 0x%08" PRIx32
".",
740 case TPM2_HT_PERMANENT
: /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
741 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
742 "Refusing to create ESYS handle for permanent handle 0x%08" PRIx32
".",
745 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
746 "Refusing to create ESYS handle for unknown handle 0x%08" PRIx32
".",
750 r
= tpm2_get_capability_handle(c
, tpm_handle
);
754 log_debug("TPM handle 0x%08" PRIx32
" not populated.", tpm_handle
);
759 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
760 r
= tpm2_handle_new(c
, &handle
);
764 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
765 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
766 handle
->flush
= false;
768 rc
= sym_Esys_TR_FromTPMPublic(
771 session
? session
->esys_handle
: ESYS_TR_NONE
,
774 &handle
->esys_handle
);
775 if (rc
!= TSS2_RC_SUCCESS
)
776 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
777 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
779 *ret_handle
= TAKE_PTR(handle
);
784 /* Copy an object in the TPM at a transient location to a persistent location.
786 * The provided transient handle must exist in the TPM in the transient range. The persistent location may be
787 * 0 or any location in the persistent range. If 0, this will try each handle in the persistent range, in
788 * ascending order, until an available one is found. If non-zero, only the requested persistent location will
791 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
792 * location(s), or < 0 on error. The persistent handle is only provided when returning 1. */
793 static int tpm2_persist_handle(
795 const Tpm2Handle
*transient_handle
,
796 const Tpm2Handle
*session
,
797 TPMI_DH_PERSISTENT persistent_location
,
798 Tpm2Handle
**ret_persistent_handle
) {
800 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
801 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
802 TPMI_DH_PERSISTENT first
= UINT32_C(0x81000000), last
= UINT32_C(0x81ffffff);
807 assert(transient_handle
);
809 /* If persistent location specified, only try that. */
810 if (persistent_location
!= 0) {
811 if (TPM2_HANDLE_TYPE(persistent_location
) != TPM2_HT_PERSISTENT
)
812 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
813 "Handle not in persistent range: 0x%x", persistent_location
);
815 first
= last
= persistent_location
;
818 for (TPMI_DH_PERSISTENT requested
= first
; requested
<= last
; requested
++) {
819 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*persistent_handle
= NULL
;
820 r
= tpm2_handle_new(c
, &persistent_handle
);
824 /* Since this is a persistent handle, don't flush it. */
825 persistent_handle
->flush
= false;
827 rc
= sym_Esys_EvictControl(
830 transient_handle
->esys_handle
,
831 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
835 &persistent_handle
->esys_handle
);
836 if (rc
== TSS2_RC_SUCCESS
) {
837 if (ret_persistent_handle
)
838 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
842 if (rc
!= TPM2_RC_NV_DEFINED
)
843 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
844 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc
));
847 if (ret_persistent_handle
)
848 *ret_persistent_handle
= NULL
;
853 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
855 static int tpm2_credit_random(Tpm2Context
*c
) {
856 size_t rps
, done
= 0;
863 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
864 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
865 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
868 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH
, F_OK
) < 0) {
870 log_debug_errno(errno
, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH
"' exists, ignoring: %m");
872 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
873 return 0; /* Already done */
876 t
= now(CLOCK_MONOTONIC
);
878 for (rps
= random_pool_size(); rps
> 0;) {
879 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
881 rc
= sym_Esys_GetRandom(
886 MIN(rps
, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
888 if (rc
!= TSS2_RC_SUCCESS
)
889 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
890 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc
));
892 if (buffer
->size
== 0)
893 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
894 "Zero-sized entropy returned from TPM.");
896 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
898 return log_error_errno(r
, "Failed wo write entropy to kernel: %m");
900 done
+= buffer
->size
;
901 rps
= LESS_BY(rps
, buffer
->size
);
904 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
906 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
908 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
913 static int tpm2_read_public(
915 const Tpm2Handle
*session
,
916 const Tpm2Handle
*handle
,
917 TPM2B_PUBLIC
**ret_public
,
918 TPM2B_NAME
**ret_name
,
919 TPM2B_NAME
**ret_qname
) {
926 rc
= sym_Esys_ReadPublic(
929 session
? session
->esys_handle
: ESYS_TR_NONE
,
935 if (rc
!= TSS2_RC_SUCCESS
)
936 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
937 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
942 /* Get one of the legacy primary key templates.
944 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
945 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
946 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
947 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
948 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
950 static const TPMT_PUBLIC legacy_ecc
= {
951 .type
= TPM2_ALG_ECC
,
952 .nameAlg
= TPM2_ALG_SHA256
,
953 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
954 .parameters
.eccDetail
= {
956 .algorithm
= TPM2_ALG_AES
,
958 .mode
.aes
= TPM2_ALG_CFB
,
960 .scheme
.scheme
= TPM2_ALG_NULL
,
961 .curveID
= TPM2_ECC_NIST_P256
,
962 .kdf
.scheme
= TPM2_ALG_NULL
,
967 static const TPMT_PUBLIC legacy_rsa
= {
968 .type
= TPM2_ALG_RSA
,
969 .nameAlg
= TPM2_ALG_SHA256
,
970 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
971 .parameters
.rsaDetail
= {
973 .algorithm
= TPM2_ALG_AES
,
975 .mode
.aes
= TPM2_ALG_CFB
,
977 .scheme
.scheme
= TPM2_ALG_NULL
,
982 assert(ret_template
);
984 if (alg
== TPM2_ALG_ECC
)
985 *ret_template
= legacy_ecc
;
986 else if (alg
== TPM2_ALG_RSA
)
987 *ret_template
= legacy_rsa
;
989 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
990 "Unsupported legacy SRK alg: 0x%x", alg
);
995 /* Get a Storage Root Key (SRK) template.
997 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
998 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
999 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1000 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1003 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1004 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1006 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1007 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1008 * (see TPM2_SRK_HANDLE and tpm2_get_srk() below).
1010 * The alg must be TPM2_ALG_RSA or TPM2_ALG_ECC. Returns error if the requested template is not supported on
1011 * this TPM. Also see tpm2_get_best_srk_template() below. */
1012 static int tpm2_get_srk_template(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1013 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1014 * Provisioning Guidance document, specifically:
1015 * TPMA_OBJECT_USERWITHAUTH is added.
1016 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1017 * TPMA_OBJECT_NODA is added. */
1018 TPMA_OBJECT srk_attributes
=
1019 TPMA_OBJECT_DECRYPT
|
1020 TPMA_OBJECT_FIXEDPARENT
|
1021 TPMA_OBJECT_FIXEDTPM
|
1023 TPMA_OBJECT_RESTRICTED
|
1024 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1025 TPMA_OBJECT_USERWITHAUTH
;
1027 /* The symmetric configuration is the same between ECC and RSA templates. */
1028 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1029 .algorithm
= TPM2_ALG_AES
,
1031 .mode
.aes
= TPM2_ALG_CFB
,
1034 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1036 /* From the EK Credential Profile template "L-2". */
1037 TPMT_PUBLIC srk_ecc
= {
1038 .type
= TPM2_ALG_ECC
,
1039 .nameAlg
= TPM2_ALG_SHA256
,
1040 .objectAttributes
= srk_attributes
,
1041 .parameters
.eccDetail
= {
1042 .symmetric
= srk_symmetric
,
1043 .scheme
.scheme
= TPM2_ALG_NULL
,
1044 .curveID
= TPM2_ECC_NIST_P256
,
1045 .kdf
.scheme
= TPM2_ALG_NULL
,
1049 /* From the EK Credential Profile template "L-1". */
1050 TPMT_PUBLIC srk_rsa
= {
1051 .type
= TPM2_ALG_RSA
,
1052 .nameAlg
= TPM2_ALG_SHA256
,
1053 .objectAttributes
= srk_attributes
,
1054 .parameters
.rsaDetail
= {
1055 .symmetric
= srk_symmetric
,
1056 .scheme
.scheme
= TPM2_ALG_NULL
,
1062 assert(ret_template
);
1064 if (alg
== TPM2_ALG_ECC
) {
1065 if (!tpm2_supports_alg(c
, TPM2_ALG_ECC
))
1066 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1067 "TPM does not support ECC.");
1069 if (!tpm2_supports_ecc_curve(c
, srk_ecc
.parameters
.eccDetail
.curveID
))
1070 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1071 "TPM does not support ECC-NIST-P256 curve.");
1073 if (!tpm2_supports_tpmt_public(c
, &srk_ecc
))
1074 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1075 "TPM does not support SRK ECC template L-2.");
1077 *ret_template
= srk_ecc
;
1081 if (alg
== TPM2_ALG_RSA
) {
1082 if (!tpm2_supports_alg(c
, TPM2_ALG_RSA
))
1083 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1084 "TPM does not support RSA.");
1086 if (!tpm2_supports_tpmt_public(c
, &srk_rsa
))
1087 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1088 "TPM does not support SRK RSA template L-1.");
1090 *ret_template
= srk_rsa
;
1094 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Unsupported SRK alg: 0x%x.", alg
);
1097 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1098 static int tpm2_get_best_srk_template(Tpm2Context
*c
, TPMT_PUBLIC
*ret_template
) {
1099 if (tpm2_get_srk_template(c
, TPM2_ALG_ECC
, ret_template
) >= 0 ||
1100 tpm2_get_srk_template(c
, TPM2_ALG_RSA
, ret_template
) >= 0)
1103 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1104 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1107 /* The SRK handle is defined in the Provisioning Guidance document (see above) in the table "Reserved Handles
1108 * for TPM Provisioning Fundamental Elements". The SRK is useful because it is "shared", meaning it has no
1109 * authValue nor authPolicy set, and thus may be used by anyone on the system to generate derived keys or
1110 * seal secrets. This is useful if the TPM has an auth (password) set for the 'owner hierarchy', which would
1111 * prevent users from generating primary transient keys, unless they knew the owner hierarchy auth. See
1112 * the Provisioning Guidance document for more details. */
1113 #define TPM2_SRK_HANDLE UINT32_C(0x81000001)
1115 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1116 * tpm2_get_or_create_srk() below. */
1117 static int tpm2_get_srk(
1119 const Tpm2Handle
*session
,
1120 TPM2B_PUBLIC
**ret_public
,
1121 TPM2B_NAME
**ret_name
,
1122 TPM2B_NAME
**ret_qname
,
1123 Tpm2Handle
**ret_handle
) {
1129 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
1130 r
= tpm2_esys_handle_from_tpm_handle(c
, session
, TPM2_SRK_HANDLE
, &handle
);
1133 if (r
== 0) { /* SRK not found */
1145 if (ret_public
|| ret_name
|| ret_qname
) {
1146 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
1152 *ret_handle
= TAKE_PTR(handle
);
1157 /* Get the SRK, creating one if needed. Returns 0 on success, or < 0 on error. */
1158 static int tpm2_get_or_create_srk(
1160 const Tpm2Handle
*session
,
1161 TPM2B_PUBLIC
**ret_public
,
1162 TPM2B_NAME
**ret_name
,
1163 TPM2B_NAME
**ret_qname
,
1164 Tpm2Handle
**ret_handle
) {
1168 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1174 /* No SRK, create and persist one */
1175 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
1176 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1178 return log_error_errno(r
, "Could not get best SRK template: %m");
1180 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1181 r
= tpm2_create_primary(
1185 /* sensitive= */ NULL
,
1186 /* ret_public= */ NULL
,
1191 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1192 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1193 * either case, all threads will get the persistent SRK below. */
1194 r
= tpm2_persist_handle(c
, transient_handle
, session
, TPM2_SRK_HANDLE
, /* ret_persistent_handle= */ NULL
);
1198 /* The SRK should exist now. */
1199 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1203 /* This should never happen. */
1204 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1209 /* Utility functions for TPMS_PCR_SELECTION. */
1211 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1212 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1214 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1217 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1218 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
1222 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1223 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPMS_PCR_SELECTION
*ret
) {
1226 /* This is currently hardcoded at 24 PCRs, above. */
1227 if (!TPM2_PCR_MASK_VALID(mask
))
1228 log_warning("PCR mask selections (%x) out of range, ignoring.",
1229 mask
& ~((uint32_t)TPM2_PCRS_MASK
));
1231 *ret
= (TPMS_PCR_SELECTION
){
1233 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1234 .pcrSelect
[0] = mask
& 0xff,
1235 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1236 .pcrSelect
[2] = (mask
>> 16) & 0xff,
1240 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1241 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1244 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1247 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1250 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
1253 /* Add all PCR selections in the mask. */
1254 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1255 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 1);
1258 /* Remove all PCR selections in the mask. */
1259 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1260 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 0);
1263 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1264 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1267 assert(a
->hash
== b
->hash
);
1269 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1272 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1273 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1276 assert(a
->hash
== b
->hash
);
1278 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1281 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1282 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION
*a
, TPMS_PCR_SELECTION
*b
) {
1286 tpm2_tpms_pcr_selection_add(a
, b
);
1287 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
1290 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1291 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1292 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1293 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1294 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1296 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1297 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1299 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1300 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1301 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1303 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1306 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1308 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1312 return strjoin(algstr
, "(", mask
, ")");
1315 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1318 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1321 /* Utility functions for TPML_PCR_SELECTION. */
1323 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1324 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION
*l
, uint32_t index
) {
1326 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1327 assert(index
< l
->count
);
1329 size_t s
= l
->count
- (index
+ 1);
1330 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
1334 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1335 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1336 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1337 static TPMS_PCR_SELECTION
*tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1338 TPML_PCR_SELECTION
*l
,
1339 TPMI_ALG_HASH hash_alg
) {
1342 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1344 TPMS_PCR_SELECTION
*selection
= NULL
;
1345 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1346 if (s
->hash
== hash_alg
) {
1354 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1355 for (uint32_t i
= l
->count
- 1; i
> 0; i
--) {
1356 TPMS_PCR_SELECTION
*s
= &l
->pcrSelections
[i
];
1361 if (s
->hash
== hash_alg
) {
1362 tpm2_tpms_pcr_selection_move(selection
, s
);
1363 tpm2_tpml_pcr_selection_remove_index(l
, i
);
1370 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1371 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION
*l
) {
1372 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1373 for (uint32_t i
= 0; i
< l
->count
; i
++)
1374 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1375 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, l
->pcrSelections
[i
].hash
);
1378 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1379 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash_alg
) {
1382 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1383 * are multiple entries with the requested hash alg. */
1384 TPML_PCR_SELECTION lcopy
= *l
;
1386 TPMS_PCR_SELECTION
*s
;
1387 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1391 return tpm2_tpms_pcr_selection_to_mask(s
);
1394 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1395 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPML_PCR_SELECTION
*ret
) {
1398 TPMS_PCR_SELECTION s
;
1399 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1401 *ret
= (TPML_PCR_SELECTION
){
1403 .pcrSelections
[0] = s
,
1407 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1408 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1409 * entries with the same hash alg. */
1410 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1414 if (tpm2_tpms_pcr_selection_is_empty(s
))
1417 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1419 tpm2_tpms_pcr_selection_add(selection
, s
);
1423 /* It's already broken if the count is higher than the array has size for. */
1424 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1426 /* If full, the cleanup should result in at least one available entry. */
1427 if (l
->count
== ELEMENTSOF(l
->pcrSelections
))
1428 tpm2_tpml_pcr_selection_cleanup(l
);
1430 assert(l
->count
< ELEMENTSOF(l
->pcrSelections
));
1431 l
->pcrSelections
[l
->count
++] = *s
;
1434 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1435 * will combine all entries for 's->hash' in 'l'. */
1436 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION
*l
, const TPMS_PCR_SELECTION
*s
) {
1440 if (tpm2_tpms_pcr_selection_is_empty(s
))
1443 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1445 tpm2_tpms_pcr_selection_sub(selection
, s
);
1448 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1449 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1452 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l
, hash
), mask
);
1455 /* Add the PCR selections in the mask, with the provided hash. */
1456 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1457 TPMS_PCR_SELECTION tpms
;
1461 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1462 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l
, &tpms
);
1465 /* Remove the PCR selections in the mask, with the provided hash. */
1466 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash
, uint32_t mask
) {
1467 TPMS_PCR_SELECTION tpms
;
1471 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1472 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l
, &tpms
);
1475 /* Add all PCR selections in 'b' to 'a'. */
1476 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1480 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1481 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a
, selection_b
);
1484 /* Remove all PCR selections in 'b' from 'a'. */
1485 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION
*a
, const TPML_PCR_SELECTION
*b
) {
1489 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1490 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a
, selection_b
);
1493 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION
*l
) {
1496 _cleanup_free_
char *banks
= NULL
;
1497 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1498 if (tpm2_tpms_pcr_selection_is_empty(s
))
1501 _cleanup_free_
char *str
= tpm2_tpms_pcr_selection_to_string(s
);
1502 if (!str
|| !strextend_with_separator(&banks
, ",", str
))
1506 return strjoin("[", strempty(banks
), "]");
1509 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION
*l
) {
1511 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1514 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
) {
1515 size_t w
= tpm2_tpms_pcr_selection_weight(s
);
1516 assert(weight
<= SIZE_MAX
- w
);
1523 bool tpm2_pcr_value_valid(const Tpm2PCRValue
*pcr_value
) {
1529 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1530 log_debug("PCR index %u invalid.", pcr_value
->index
);
1534 /* If it contains a value, the value size must match the hash size. */
1535 if (pcr_value
->value
.size
> 0) {
1536 r
= tpm2_hash_alg_to_size(pcr_value
->hash
);
1540 if (pcr_value
->value
.size
!= (size_t) r
) {
1541 log_debug("PCR hash 0x%" PRIx16
" expected size %d does not match actual size %" PRIu16
".",
1542 pcr_value
->hash
, r
, pcr_value
->value
.size
);
1550 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1552 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1553 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1555 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1557 bool tpm2_pcr_values_valid(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1558 if (!pcr_values
&& n_pcr_values
> 0)
1561 const Tpm2PCRValue
*previous
= NULL
;
1562 FOREACH_ARRAY(current
, pcr_values
, n_pcr_values
) {
1563 if (!tpm2_pcr_value_valid(current
))
1571 /* Hashes must be sorted in ascending order */
1572 if (current
->hash
< previous
->hash
) {
1573 log_debug("PCR values not in ascending order, hash %" PRIu16
" is after %" PRIu16
".",
1574 current
->hash
, previous
->hash
);
1578 if (current
->hash
== previous
->hash
) {
1579 /* Indexes (for the same hash) must be sorted in ascending order */
1580 if (current
->index
< previous
->index
) {
1581 log_debug("PCR values not in ascending order, hash %" PRIu16
" index %u is after %u.",
1582 current
->hash
, current
->index
, previous
->index
);
1586 /* Indexes (for the same hash) must not be duplicates */
1587 if (current
->index
== previous
->index
) {
1588 log_debug("PCR values contain duplicates for hash %" PRIu16
" index %u.",
1589 current
->hash
, previous
->index
);
1598 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1599 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1600 assert(pcr_values
|| n_pcr_values
== 0);
1602 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1603 if (v
->value
.size
> 0)
1609 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1610 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1611 assert(pcr_values
|| n_pcr_values
== 0);
1613 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1614 if (v
->value
.size
== 0)
1620 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1624 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
1627 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1628 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1629 void tpm2_sort_pcr_values(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1630 typesafe_qsort(pcr_values
, n_pcr_values
, cmp_pcr_values
);
1633 int tpm2_pcr_values_from_mask(uint32_t mask
, TPMI_ALG_HASH hash
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1634 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1635 size_t n_pcr_values
= 0;
1637 assert(ret_pcr_values
);
1638 assert(ret_n_pcr_values
);
1640 FOREACH_PCR_IN_MASK(index
, mask
)
1641 if (!GREEDY_REALLOC_APPEND(
1644 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1646 return log_oom_debug();
1648 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1649 *ret_n_pcr_values
= n_pcr_values
;
1654 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1657 assert(pcr_values
|| n_pcr_values
== 0);
1660 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1661 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1663 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1664 if (v
->hash
== hash
)
1665 SET_BIT(mask
, v
->index
);
1672 int tpm2_tpml_pcr_selection_from_pcr_values(
1673 const Tpm2PCRValue
*pcr_values
,
1674 size_t n_pcr_values
,
1675 TPML_PCR_SELECTION
*ret_selection
,
1676 TPM2B_DIGEST
**ret_values
,
1677 size_t *ret_n_values
) {
1679 TPML_PCR_SELECTION selection
= {};
1680 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1681 size_t n_values
= 0;
1683 assert(pcr_values
|| n_pcr_values
== 0);
1685 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1686 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR values are not valid.");
1688 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1689 tpm2_tpml_pcr_selection_add_mask(&selection
, v
->hash
, INDEX_TO_MASK(uint32_t, v
->index
));
1691 if (!GREEDY_REALLOC_APPEND(values
, n_values
, &v
->value
, 1))
1692 return log_oom_debug();
1696 *ret_selection
= selection
;
1698 *ret_values
= TAKE_PTR(values
);
1700 *ret_n_values
= n_values
;
1705 /* Count the number of different hash algorithms for all the entries. */
1706 int tpm2_pcr_values_hash_count(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, size_t *ret_count
) {
1707 TPML_PCR_SELECTION selection
;
1713 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1717 /* ret_values= */ NULL
,
1718 /* ret_n_values= */ NULL
);
1722 *ret_count
= selection
.count
;
1727 /* Parse a string argument into a Tpm2PCRValue object.
1729 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1730 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1731 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1732 int tpm2_pcr_value_from_string(const char *arg
, Tpm2PCRValue
*ret_pcr_value
) {
1733 Tpm2PCRValue pcr_value
= {};
1734 const char *p
= arg
;
1738 assert(ret_pcr_value
);
1740 _cleanup_free_
char *index
= NULL
;
1741 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1743 return log_error_errno(r
, "Could not parse pcr value '%s': %m", p
);
1745 r
= tpm2_pcr_index_from_string(index
);
1747 return log_error_errno(r
, "Invalid pcr index '%s': %m", index
);
1748 pcr_value
.index
= (unsigned) r
;
1751 _cleanup_free_
char *hash
= NULL
;
1752 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1754 return log_error_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1756 r
= tpm2_hash_alg_from_string(hash
);
1758 return log_error_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1759 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1762 /* Remove leading 0x if present */
1763 p
= startswith_no_case(p
, "0x") ?: p
;
1765 _cleanup_free_
void *buf
= NULL
;
1766 size_t buf_size
= 0;
1767 r
= unhexmem(p
, SIZE_MAX
, &buf
, &buf_size
);
1769 return log_error_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1771 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1773 return log_error_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1775 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1779 *ret_pcr_value
= pcr_value
;
1784 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1785 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1786 * string. This does not check for validity. */
1787 char *tpm2_pcr_value_to_string(const Tpm2PCRValue
*pcr_value
) {
1788 _cleanup_free_
char *index
= NULL
, *value
= NULL
;
1790 if (asprintf(&index
, "%u", pcr_value
->index
) < 0)
1793 const char *hash
= pcr_value
->hash
> 0 ? tpm2_hash_alg_to_string(pcr_value
->hash
) : NULL
;
1795 if (hash
&& pcr_value
->value
.size
> 0) {
1796 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1801 return strjoin(index
, hash
? ":" : "", strempty(hash
), value
? "=" : "", strempty(value
));
1804 /* Parse a string argument into an array of Tpm2PCRValue objects.
1806 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1807 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1808 int tpm2_pcr_values_from_string(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1809 const char *p
= arg
;
1813 assert(ret_pcr_values
);
1814 assert(ret_n_pcr_values
);
1816 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1817 size_t n_pcr_values
= 0;
1820 _cleanup_free_
char *pcr_arg
= NULL
;
1821 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1823 return log_error_errno(r
, "Could not parse pcr values '%s': %m", p
);
1827 Tpm2PCRValue pcr_value
;
1828 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1832 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1836 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1837 *ret_n_pcr_values
= n_pcr_values
;
1842 /* Return a string representing the array of PCR values. The format is as described in
1843 * tpm2_pcr_values_from_string(). This does not check for validity. */
1844 char *tpm2_pcr_values_to_string(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1845 _cleanup_free_
char *s
= NULL
;
1847 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
1848 _cleanup_free_
char *pcrstr
= tpm2_pcr_value_to_string(v
);
1849 if (!pcrstr
|| !strextend_with_separator(&s
, "+", pcrstr
))
1853 return s
? TAKE_PTR(s
) : strdup("");
1856 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
1857 if (!DEBUG_LOGGING
|| !l
)
1860 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
1861 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
1864 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
1865 if (!DEBUG_LOGGING
|| !pcr_value
)
1868 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
1869 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
1872 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
1873 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
1876 _cleanup_free_
char *h
= hexmem(buffer
, size
);
1877 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
1880 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
1882 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
1885 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
1887 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
1890 static int tpm2_get_policy_digest(
1892 const Tpm2Handle
*session
,
1893 TPM2B_DIGEST
**ret_policy_digest
) {
1897 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
1903 log_debug("Acquiring policy digest.");
1905 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
1906 rc
= sym_Esys_PolicyGetDigest(
1908 session
->esys_handle
,
1913 if (rc
!= TSS2_RC_SUCCESS
)
1914 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1915 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc
));
1917 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
1919 if (ret_policy_digest
)
1920 *ret_policy_digest
= TAKE_PTR(policy_digest
);
1925 int tpm2_create_primary(
1927 const Tpm2Handle
*session
,
1928 const TPM2B_PUBLIC
*template,
1929 const TPM2B_SENSITIVE_CREATE
*sensitive
,
1930 TPM2B_PUBLIC
**ret_public
,
1931 Tpm2Handle
**ret_handle
) {
1940 log_debug("Creating primary key on TPM.");
1942 ts
= now(CLOCK_MONOTONIC
);
1944 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
1945 r
= tpm2_handle_new(c
, &handle
);
1949 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
1950 rc
= sym_Esys_CreatePrimary(
1953 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
1956 sensitive
? sensitive
: &(TPM2B_SENSITIVE_CREATE
) {},
1958 /* outsideInfo= */ NULL
,
1959 &(TPML_PCR_SELECTION
) {},
1960 &handle
->esys_handle
,
1962 /* creationData= */ NULL
,
1963 /* creationHash= */ NULL
,
1964 /* creationTicket= */ NULL
);
1965 if (rc
!= TSS2_RC_SUCCESS
)
1966 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1967 "Failed to generate primary key in TPM: %s",
1968 sym_Tss2_RC_Decode(rc
));
1970 log_debug("Successfully created primary key on TPM in %s.",
1971 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
1974 *ret_public
= TAKE_PTR(public);
1976 *ret_handle
= TAKE_PTR(handle
);
1981 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
1982 * instead use tpm2_create_primary(). */
1983 int tpm2_create(Tpm2Context
*c
,
1984 const Tpm2Handle
*parent
,
1985 const Tpm2Handle
*session
,
1986 const TPMT_PUBLIC
*template,
1987 const TPMS_SENSITIVE_CREATE
*sensitive
,
1988 TPM2B_PUBLIC
**ret_public
,
1989 TPM2B_PRIVATE
**ret_private
) {
1998 log_debug("Creating object on TPM.");
2000 ts
= now(CLOCK_MONOTONIC
);
2002 TPM2B_PUBLIC tpm2b_public
= {
2003 .size
= sizeof(*template) - sizeof(template->unique
),
2004 .publicArea
= *template,
2007 /* Zero the unique area. */
2008 zero(tpm2b_public
.publicArea
.unique
);
2010 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2012 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2013 .size
= sizeof(*sensitive
),
2014 .sensitive
= *sensitive
,
2017 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2019 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2020 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2021 rc
= sym_Esys_Create(
2023 parent
->esys_handle
,
2024 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2029 /* outsideInfo= */ NULL
,
2030 &(TPML_PCR_SELECTION
) {},
2033 /* creationData= */ NULL
,
2034 /* creationHash= */ NULL
,
2035 /* creationTicket= */ NULL
);
2036 if (rc
!= TSS2_RC_SUCCESS
)
2037 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2038 "Failed to generate object in TPM: %s",
2039 sym_Tss2_RC_Decode(rc
));
2041 log_debug("Successfully created object on TPM in %s.",
2042 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2045 *ret_public
= TAKE_PTR(public);
2047 *ret_private
= TAKE_PTR(private);
2052 static int tpm2_load(
2054 const Tpm2Handle
*parent
,
2055 const Tpm2Handle
*session
,
2056 const TPM2B_PUBLIC
*public,
2057 const TPM2B_PRIVATE
*private,
2058 Tpm2Handle
**ret_handle
) {
2068 log_debug("Loading object into TPM.");
2070 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2071 r
= tpm2_handle_new(c
, &handle
);
2077 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2078 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2083 &handle
->esys_handle
);
2084 if (rc
== TPM2_RC_LOCKOUT
)
2085 return log_error_errno(SYNTHETIC_ERRNO(ENOLCK
),
2086 "TPM2 device is in dictionary attack lockout mode.");
2087 if (rc
!= TSS2_RC_SUCCESS
)
2088 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2089 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2091 *ret_handle
= TAKE_PTR(handle
);
2096 static int tpm2_load_external(
2098 const Tpm2Handle
*session
,
2099 const TPM2B_PUBLIC
*public,
2100 const TPM2B_SENSITIVE
*private,
2101 Tpm2Handle
**ret_handle
) {
2109 log_debug("Loading external key into TPM.");
2111 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2112 r
= tpm2_handle_new(c
, &handle
);
2116 rc
= sym_Esys_LoadExternal(
2118 session
? session
->esys_handle
: ESYS_TR_NONE
,
2124 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2125 * hierarchy, older versions need TPM2_RH_* instead. */
2130 &handle
->esys_handle
);
2131 if (rc
!= TSS2_RC_SUCCESS
)
2132 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2133 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2135 *ret_handle
= TAKE_PTR(handle
);
2140 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2141 * use tpm2_create_loaded(). */
2142 static int _tpm2_create_loaded(
2144 const Tpm2Handle
*parent
,
2145 const Tpm2Handle
*session
,
2146 const TPMT_PUBLIC
*template,
2147 const TPMS_SENSITIVE_CREATE
*sensitive
,
2148 TPM2B_PUBLIC
**ret_public
,
2149 TPM2B_PRIVATE
**ret_private
,
2150 Tpm2Handle
**ret_handle
) {
2160 log_debug("Creating loaded object on TPM.");
2162 ts
= now(CLOCK_MONOTONIC
);
2164 /* Copy the input template and zero the unique area. */
2165 TPMT_PUBLIC template_copy
= *template;
2166 zero(template_copy
.unique
);
2168 TPM2B_TEMPLATE tpm2b_template
;
2170 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2172 tpm2b_template
.buffer
,
2173 sizeof(tpm2b_template
.buffer
),
2175 if (rc
!= TSS2_RC_SUCCESS
)
2176 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2177 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc
));
2178 assert(size
<= UINT16_MAX
);
2179 tpm2b_template
.size
= size
;
2181 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2183 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2184 .size
= sizeof(*sensitive
),
2185 .sensitive
= *sensitive
,
2188 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2190 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2191 r
= tpm2_handle_new(c
, &handle
);
2195 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2196 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2197 rc
= sym_Esys_CreateLoaded(
2199 parent
->esys_handle
,
2200 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2205 &handle
->esys_handle
,
2208 if (rc
!= TSS2_RC_SUCCESS
)
2209 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2210 "Failed to generate loaded object in TPM: %s",
2211 sym_Tss2_RC_Decode(rc
));
2213 log_debug("Successfully created loaded object on TPM in %s.",
2214 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2217 *ret_public
= TAKE_PTR(public);
2219 *ret_private
= TAKE_PTR(private);
2221 *ret_handle
= TAKE_PTR(handle
);
2226 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2227 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2228 * tpm2_create_primary(). */
2229 int tpm2_create_loaded(
2231 const Tpm2Handle
*parent
,
2232 const Tpm2Handle
*session
,
2233 const TPMT_PUBLIC
*template,
2234 const TPMS_SENSITIVE_CREATE
*sensitive
,
2235 TPM2B_PUBLIC
**ret_public
,
2236 TPM2B_PRIVATE
**ret_private
,
2237 Tpm2Handle
**ret_handle
) {
2241 if (tpm2_supports_command(c
, TPM2_CC_CreateLoaded
))
2242 return _tpm2_create_loaded(c
, parent
, session
, template, sensitive
, ret_public
, ret_private
, ret_handle
);
2244 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2245 * create and load manually. */
2246 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2247 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2248 r
= tpm2_create(c
, parent
, session
, template, sensitive
, &public, &private);
2252 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2253 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2258 *ret_public
= TAKE_PTR(public);
2260 *ret_private
= TAKE_PTR(private);
2262 *ret_handle
= TAKE_PTR(handle
);
2267 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2268 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2269 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2270 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2274 const TPML_PCR_SELECTION
*pcr_selection
,
2275 Tpm2PCRValue
**ret_pcr_values
,
2276 size_t *ret_n_pcr_values
) {
2278 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2279 size_t n_pcr_values
= 0;
2283 assert(pcr_selection
);
2284 assert(ret_pcr_values
);
2285 assert(ret_n_pcr_values
);
2287 TPML_PCR_SELECTION remaining
= *pcr_selection
;
2288 while (!tpm2_tpml_pcr_selection_is_empty(&remaining
)) {
2289 _cleanup_(Esys_Freep
) TPML_PCR_SELECTION
*current_read
= NULL
;
2290 _cleanup_(Esys_Freep
) TPML_DIGEST
*current_values
= NULL
;
2292 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2294 /* Unfortunately, PCR_Read will not return more than 8 values. */
2295 rc
= sym_Esys_PCR_Read(
2304 if (rc
!= TSS2_RC_SUCCESS
)
2305 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2306 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc
));
2308 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2310 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2311 log_warning("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2316 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2317 assert(i
< current_values
->count
);
2318 Tpm2PCRValue pcr_value
= {
2321 .value
= current_values
->digests
[i
++],
2324 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2326 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2329 assert(i
== current_values
->count
);
2331 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2334 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
2336 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
2337 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "PCR values read from TPM are not valid.");
2339 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2340 *ret_n_pcr_values
= n_pcr_values
;
2345 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2346 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2347 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2348 * appropriate entries, this returns an error. This does not check the array for validity. */
2349 int tpm2_pcr_read_missing_values(Tpm2Context
*c
, Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2350 TPMI_ALG_HASH pcr_bank
= 0;
2354 assert(pcr_values
|| n_pcr_values
== 0);
2356 if (n_pcr_values
> 0) {
2358 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2360 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
2362 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2364 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2368 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2374 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2378 if (v
->value
.size
> 0)
2381 TPML_PCR_SELECTION selection
;
2382 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
2386 _cleanup_free_ Tpm2PCRValue
*read_values
= NULL
;
2387 size_t n_read_values
;
2388 r
= tpm2_pcr_read(c
, &selection
, &read_values
, &n_read_values
);
2392 if (n_read_values
== 0)
2393 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2394 "Could not read PCR hash 0x%" PRIu16
" index %u",
2397 assert(n_read_values
== 1);
2398 assert(read_values
[0].hash
== v
->hash
);
2399 assert(read_values
[0].index
== v
->index
);
2401 v
->value
= read_values
[0].value
;
2407 static int tpm2_pcr_mask_good(
2412 TPML_PCR_SELECTION selection
;
2417 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2418 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2419 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2421 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
2423 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2424 size_t n_pcr_values
;
2425 r
= tpm2_pcr_read(c
, &selection
, &pcr_values
, &n_pcr_values
);
2429 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2430 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
2431 if (!memeqbyte(0x00, v
->value
.buffer
, v
->value
.size
) &&
2432 !memeqbyte(0xFF, v
->value
.buffer
, v
->value
.size
))
2438 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
2442 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2443 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2444 if (selection
->sizeofSelect
< TPM2_PCRS_MAX
/8) {
2445 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2446 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2450 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
2452 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2453 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2455 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2456 if (selection
->pcrSelect
[j
] != 0xFF) {
2462 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2463 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2468 int tpm2_get_best_pcr_bank(
2471 TPMI_ALG_HASH
*ret
) {
2473 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
2479 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2480 TPMI_ALG_HASH hash
= selection
->hash
;
2483 /* For now we are only interested in the SHA1 and SHA256 banks */
2484 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2487 r
= tpm2_bank_has24(selection
);
2493 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2497 if (hash
== TPM2_ALG_SHA256
) {
2498 supported_hash
= TPM2_ALG_SHA256
;
2500 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2501 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2505 assert(hash
== TPM2_ALG_SHA1
);
2507 if (supported_hash
== 0)
2508 supported_hash
= TPM2_ALG_SHA1
;
2510 if (good
&& hash_with_valid_pcr
== 0)
2511 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
2515 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2516 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2519 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2520 * not initialized. */
2522 if (hash_with_valid_pcr
== TPM2_ALG_SHA256
) {
2523 assert(supported_hash
== TPM2_ALG_SHA256
);
2524 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2525 *ret
= TPM2_ALG_SHA256
;
2526 } else if (hash_with_valid_pcr
== TPM2_ALG_SHA1
) {
2527 if (supported_hash
== TPM2_ALG_SHA256
)
2528 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.");
2530 assert(supported_hash
== TPM2_ALG_SHA1
);
2531 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.");
2534 *ret
= TPM2_ALG_SHA1
;
2535 } else if (supported_hash
== TPM2_ALG_SHA256
) {
2536 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!");
2537 *ret
= TPM2_ALG_SHA256
;
2538 } else if (supported_hash
== TPM2_ALG_SHA1
) {
2539 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!");
2540 *ret
= TPM2_ALG_SHA1
;
2542 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2543 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2548 int tpm2_get_good_pcr_banks(
2551 TPMI_ALG_HASH
**ret
) {
2553 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2554 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2560 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2561 TPMI_ALG_HASH hash
= selection
->hash
;
2563 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2564 r
= tpm2_bank_has24(selection
);
2570 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2571 r
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2575 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2576 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2579 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2582 good_banks
[n_good_banks
++] = hash
;
2584 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2587 fallback_banks
[n_fallback_banks
++] = hash
;
2591 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2592 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2593 if (n_good_banks
> 0) {
2594 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks
);
2595 *ret
= TAKE_PTR(good_banks
);
2596 return (int) n_good_banks
;
2598 if (n_fallback_banks
> 0) {
2599 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks
);
2600 *ret
= TAKE_PTR(fallback_banks
);
2601 return (int) n_fallback_banks
;
2604 /* No suitable banks found. */
2609 int tpm2_get_good_pcr_banks_strv(
2615 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2616 _cleanup_strv_free_
char **l
= NULL
;
2622 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2626 FOREACH_ARRAY(a
, algs
, n_algs
) {
2627 _cleanup_free_
char *n
= NULL
;
2628 const EVP_MD
*implementation
;
2631 salg
= tpm2_hash_alg_to_string(*a
);
2633 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
2635 implementation
= EVP_get_digestbyname(salg
);
2636 if (!implementation
)
2637 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2639 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2643 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2645 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2651 #else /* HAVE_OPENSSL */
2652 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2656 /* Hash data into the digest.
2658 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2659 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2660 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2661 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2663 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2664 * correct for 'alg'.
2666 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2667 int tpm2_digest_many(
2669 TPM2B_DIGEST
*digest
,
2670 const struct iovec data
[],
2674 struct sha256_ctx ctx
;
2677 assert(data
|| n_data
== 0);
2679 if (alg
!= TPM2_ALG_SHA256
)
2680 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2681 "Hash algorithm not supported: 0x%x", alg
);
2683 if (extend
&& digest
->size
!= SHA256_DIGEST_SIZE
)
2684 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2685 "Digest size 0x%x, require 0x%x",
2686 digest
->size
, (unsigned)SHA256_DIGEST_SIZE
);
2688 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2689 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
2693 sha256_init_ctx(&ctx
);
2696 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
2698 *digest
= (TPM2B_DIGEST
){ .size
= SHA256_DIGEST_SIZE
, };
2699 if (n_data
== 0) /* If not extending and no data, return zero hash */
2703 FOREACH_ARRAY(d
, data
, n_data
)
2704 sha256_process_bytes(d
->iov_base
, d
->iov_len
, &ctx
);
2706 sha256_finish_ctx(&ctx
, digest
->buffer
);
2711 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2712 int tpm2_digest_many_digests(
2714 TPM2B_DIGEST
*digest
,
2715 const TPM2B_DIGEST data
[],
2719 _cleanup_free_
struct iovec
*iovecs
= NULL
;
2721 assert(data
|| n_data
== 0);
2723 iovecs
= new(struct iovec
, n_data
);
2727 for (size_t i
= 0; i
< n_data
; i
++)
2728 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
2730 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
2733 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
2734 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
2735 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
2736 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
2737 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2739 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2740 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2741 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2742 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2744 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2745 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2746 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2748 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2749 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2750 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2751 * which we will trim the 0(s) from before sending to the TPM.
2753 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
2754 bool trimmed
= false;
2758 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
2764 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2767 static int tpm2_get_pin_auth(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
2768 TPM2B_AUTH auth
= {};
2774 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
2778 tpm2_trim_auth_value(&auth
);
2780 *ret_auth
= TAKE_STRUCT(auth
);
2785 static int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
2786 TPM2B_AUTH auth
= {};
2796 CLEANUP_ERASE(auth
);
2798 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &auth
);
2802 rc
= sym_Esys_TR_SetAuth(c
->esys_context
, handle
->esys_handle
, &auth
);
2803 if (rc
!= TSS2_RC_SUCCESS
)
2804 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2805 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc
));
2810 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
2811 TPMA_SESSION flags
= 0;
2817 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
2818 if (rc
!= TSS2_RC_SUCCESS
)
2821 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
2824 static int tpm2_make_encryption_session(
2826 const Tpm2Handle
*primary
,
2827 const Tpm2Handle
*bind_key
,
2828 Tpm2Handle
**ret_session
) {
2830 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
2831 TPMA_SESSION_CONTINUESESSION
;
2836 assert(ret_session
);
2838 log_debug("Starting HMAC encryption session.");
2840 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2841 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2842 * recover the salt, which is then used for key derivation. */
2843 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2844 r
= tpm2_handle_new(c
, &session
);
2848 rc
= sym_Esys_StartAuthSession(
2850 primary
->esys_handle
,
2851 bind_key
->esys_handle
,
2857 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2859 &session
->esys_handle
);
2860 if (rc
!= TSS2_RC_SUCCESS
)
2861 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2862 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2864 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2865 * always used for sessions), this provides confidentiality, integrity and replay protection for
2866 * operations that use this session. */
2867 rc
= sym_Esys_TRSess_SetAttributes(c
->esys_context
, session
->esys_handle
, sessionAttributes
, 0xff);
2868 if (rc
!= TSS2_RC_SUCCESS
)
2869 return log_error_errno(
2870 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2871 "Failed to configure TPM session: %s",
2872 sym_Tss2_RC_Decode(rc
));
2874 *ret_session
= TAKE_PTR(session
);
2879 static int tpm2_make_policy_session(
2881 const Tpm2Handle
*primary
,
2882 const Tpm2Handle
*encryption_session
,
2883 Tpm2Handle
**ret_session
) {
2890 assert(encryption_session
);
2891 assert(ret_session
);
2893 if (!tpm2_is_encryption_session(c
, encryption_session
))
2894 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2895 "Missing encryption session");
2897 log_debug("Starting policy session.");
2899 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2900 r
= tpm2_handle_new(c
, &session
);
2904 rc
= sym_Esys_StartAuthSession(
2906 primary
->esys_handle
,
2908 encryption_session
->esys_handle
,
2913 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2915 &session
->esys_handle
);
2916 if (rc
!= TSS2_RC_SUCCESS
)
2917 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2918 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2920 *ret_session
= TAKE_PTR(session
);
2925 static int find_signature(
2927 const TPML_PCR_SELECTION
*pcr_selection
,
2932 void *ret_signature
,
2933 size_t *ret_signature_size
) {
2940 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
2941 * public key, and policy digest. */
2943 if (!json_variant_is_object(v
))
2944 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
2946 uint16_t pcr_bank
= pcr_selection
->pcrSelections
[0].hash
;
2947 uint32_t pcr_mask
= tpm2_tpml_pcr_selection_to_mask(pcr_selection
, pcr_bank
);
2949 k
= tpm2_hash_alg_to_string(pcr_bank
);
2951 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
2953 /* First, find field by bank */
2954 b
= json_variant_by_key(v
, k
);
2956 return log_error_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
2958 if (!json_variant_is_array(b
))
2959 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
2961 /* Now iterate through all signatures known for this bank */
2962 JSON_VARIANT_ARRAY_FOREACH(i
, b
) {
2963 _cleanup_free_
void *fpj_data
= NULL
, *polj_data
= NULL
;
2964 JsonVariant
*maskj
, *fpj
, *sigj
, *polj
;
2965 size_t fpj_size
, polj_size
;
2966 uint32_t parsed_mask
;
2968 if (!json_variant_is_object(i
))
2969 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
2971 /* Check if the PCR mask matches our expectations */
2972 maskj
= json_variant_by_key(i
, "pcrs");
2976 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
2978 return log_error_errno(r
, "Failed to parse JSON PCR mask");
2980 if (parsed_mask
!= pcr_mask
)
2981 continue; /* Not for this PCR mask */
2983 /* Then check if this is for the public key we operate with */
2984 fpj
= json_variant_by_key(i
, "pkfp");
2988 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
2990 return log_error_errno(r
, "Failed to decode fingerprint in JSON data: %m");
2992 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
2993 continue; /* Not for this public key */
2995 /* Finally, check if this is for the PCR policy we expect this to be */
2996 polj
= json_variant_by_key(i
, "pol");
3000 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
3002 return log_error_errno(r
, "Failed to decode policy hash JSON data: %m");
3004 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
3007 /* This entry matches all our expectations, now return the signature included in it */
3008 sigj
= json_variant_by_key(i
, "sig");
3012 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
3015 return log_error_errno(SYNTHETIC_ERRNO(ENXIO
), "Couldn't find signature for this PCR bank, PCR index and public key.");
3016 #else /* HAVE_OPENSSL */
3017 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3021 /* Calculates the "name" of a public key.
3023 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3024 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3025 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3026 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3027 * that would also change the key name.
3029 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3030 * nameAlg is not TPM2_ALG_SHA256. */
3031 int tpm2_calculate_name(const TPMT_PUBLIC
*public, TPM2B_NAME
*ret_name
) {
3040 return log_error_errno(r
, "TPM2 support not installed: %m");
3042 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3043 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3044 "Unsupported nameAlg: 0x%x",
3047 _cleanup_free_
uint8_t *buf
= NULL
;
3050 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3054 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf
, sizeof(TPMT_PUBLIC
), &size
);
3055 if (rc
!= TSS2_RC_SUCCESS
)
3056 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3057 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3059 TPM2B_DIGEST digest
= {};
3060 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3065 .hashAlg
= TPM2_ALG_SHA256
,
3067 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3068 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3072 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3073 if (rc
!= TSS2_RC_SUCCESS
)
3074 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3075 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc
));
3078 tpm2_log_debug_name(&name
, "Calculated name");
3085 /* Get the "name" of a key from the TPM.
3087 * The "name" of a key is explained above in tpm2_calculate_name().
3089 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3090 * public/private keypair. */
3091 static int tpm2_get_name(
3093 const Tpm2Handle
*handle
,
3094 TPM2B_NAME
**ret_name
) {
3096 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
3103 rc
= sym_Esys_TR_GetName(c
->esys_context
, handle
->esys_handle
, &name
);
3104 if (rc
!= TSS2_RC_SUCCESS
)
3105 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3106 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc
));
3108 tpm2_log_debug_name(name
, "Object name");
3110 *ret_name
= TAKE_PTR(name
);
3115 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3116 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST
*digest
) {
3117 TPM2_CC command
= TPM2_CC_PolicyAuthValue
;
3122 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3126 return log_error_errno(r
, "TPM2 support not installed: %m");
3128 uint8_t buf
[sizeof(command
)];
3131 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3132 if (rc
!= TSS2_RC_SUCCESS
)
3133 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3134 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc
));
3136 if (offset
!= sizeof(command
))
3137 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3138 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3140 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3144 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3149 static int tpm2_policy_auth_value(
3151 const Tpm2Handle
*session
,
3152 TPM2B_DIGEST
**ret_policy_digest
) {
3159 log_debug("Adding authValue policy.");
3161 rc
= sym_Esys_PolicyAuthValue(
3163 session
->esys_handle
,
3167 if (rc
!= TSS2_RC_SUCCESS
)
3168 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3169 "Failed to add authValue policy to TPM: %s",
3170 sym_Tss2_RC_Decode(rc
));
3172 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3175 /* Extend 'digest' with the PolicyPCR calculated hash. */
3176 int tpm2_calculate_policy_pcr(
3177 const Tpm2PCRValue
*pcr_values
,
3178 size_t n_pcr_values
,
3179 TPM2B_DIGEST
*digest
) {
3181 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3185 assert(pcr_values
|| n_pcr_values
== 0);
3187 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3191 return log_error_errno(r
, "TPM2 support not installed: %m");
3193 TPML_PCR_SELECTION pcr_selection
;
3194 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3196 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3198 return log_error_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3200 TPM2B_DIGEST hash
= {};
3201 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3205 _cleanup_free_
uint8_t *buf
= NULL
;
3206 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3208 buf
= malloc(maxsize
);
3212 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, maxsize
, &size
);
3213 if (rc
!= TSS2_RC_SUCCESS
)
3214 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3215 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc
));
3217 rc
= sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection
, buf
, maxsize
, &size
);
3218 if (rc
!= TSS2_RC_SUCCESS
)
3219 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3220 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc
));
3222 struct iovec data
[] = {
3223 IOVEC_MAKE(buf
, size
),
3224 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3226 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3230 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3235 static int tpm2_policy_pcr(
3237 const Tpm2Handle
*session
,
3238 const TPML_PCR_SELECTION
*pcr_selection
,
3239 TPM2B_DIGEST
**ret_policy_digest
) {
3245 assert(pcr_selection
);
3247 log_debug("Adding PCR hash policy.");
3249 rc
= sym_Esys_PolicyPCR(
3251 session
->esys_handle
,
3257 if (rc
!= TSS2_RC_SUCCESS
)
3258 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3259 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc
));
3261 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3264 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3265 int tpm2_calculate_policy_authorize(
3266 const TPM2B_PUBLIC
*public,
3267 const TPM2B_DIGEST
*policy_ref
,
3268 TPM2B_DIGEST
*digest
) {
3270 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3276 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3280 return log_error_errno(r
, "TPM2 support not installed: %m");
3282 uint8_t buf
[sizeof(command
)];
3285 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3286 if (rc
!= TSS2_RC_SUCCESS
)
3287 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3288 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc
));
3290 if (offset
!= sizeof(command
))
3291 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3292 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
3294 TPM2B_NAME name
= {};
3295 r
= tpm2_calculate_name(&public->publicArea
, &name
);
3299 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3300 zero(digest
->buffer
);
3302 struct iovec data
[] = {
3303 IOVEC_MAKE(buf
, offset
),
3304 IOVEC_MAKE(name
.name
, name
.size
),
3306 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3310 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3312 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
3314 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
3318 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
3323 static int tpm2_policy_authorize(
3325 const Tpm2Handle
*session
,
3326 TPML_PCR_SELECTION
*pcr_selection
,
3327 const TPM2B_PUBLIC
*public,
3330 JsonVariant
*signature_json
,
3331 TPM2B_DIGEST
**ret_policy_digest
) {
3338 assert(pcr_selection
);
3340 assert(fp
&& fp_size
> 0);
3342 log_debug("Adding PCR signature policy.");
3344 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
3345 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
3349 /* Acquire the "name" of what we just loaded */
3350 _cleanup_(Esys_Freep
) TPM2B_NAME
*pubkey_name
= NULL
;
3351 r
= tpm2_get_name(c
, pubkey_handle
, &pubkey_name
);
3355 /* If we have a signature, proceed with verifying the PCR digest */
3356 const TPMT_TK_VERIFIED
*check_ticket
;
3357 _cleanup_(Esys_Freep
) TPMT_TK_VERIFIED
*check_ticket_buffer
= NULL
;
3358 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*approved_policy
= NULL
;
3359 if (signature_json
) {
3360 r
= tpm2_policy_pcr(
3368 _cleanup_free_
void *signature_raw
= NULL
;
3369 size_t signature_size
;
3375 approved_policy
->buffer
,
3376 approved_policy
->size
,
3382 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3383 * hence we need to do the SHA256 part ourselves, first */
3384 TPM2B_DIGEST signature_hash
= *approved_policy
;
3385 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, &signature_hash
);
3389 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
3391 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
3393 TPMT_SIGNATURE policy_signature
= {
3394 .sigAlg
= TPM2_ALG_RSASSA
,
3395 .signature
.rsassa
= {
3396 .hash
= TPM2_ALG_SHA256
,
3397 .sig
= TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw
, signature_size
),
3401 rc
= sym_Esys_VerifySignature(
3403 pubkey_handle
->esys_handle
,
3409 &check_ticket_buffer
);
3410 if (rc
!= TSS2_RC_SUCCESS
)
3411 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3412 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc
));
3414 check_ticket
= check_ticket_buffer
;
3416 /* When enrolling, we pass a NULL ticket */
3417 static const TPMT_TK_VERIFIED check_ticket_null
= {
3418 .tag
= TPM2_ST_VERIFIED
,
3419 .hierarchy
= TPM2_RH_OWNER
,
3422 check_ticket
= &check_ticket_null
;
3425 rc
= sym_Esys_PolicyAuthorize(
3427 session
->esys_handle
,
3432 /* policyRef= */ &(const TPM2B_NONCE
) {},
3435 if (rc
!= TSS2_RC_SUCCESS
)
3436 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3437 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc
));
3439 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3442 /* Extend 'digest' with the calculated policy hash. */
3443 int tpm2_calculate_sealing_policy(
3444 const Tpm2PCRValue
*pcr_values
,
3445 size_t n_pcr_values
,
3446 const TPM2B_PUBLIC
*public,
3448 TPM2B_DIGEST
*digest
) {
3452 assert(pcr_values
|| n_pcr_values
== 0);
3456 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
3461 if (n_pcr_values
> 0) {
3462 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
3468 r
= tpm2_calculate_policy_auth_value(digest
);
3476 static int tpm2_build_sealing_policy(
3478 const Tpm2Handle
*session
,
3479 uint32_t hash_pcr_mask
,
3481 const TPM2B_PUBLIC
*public,
3484 uint32_t pubkey_pcr_mask
,
3485 JsonVariant
*signature_json
,
3487 TPM2B_DIGEST
**ret_policy_digest
) {
3493 assert(pubkey_pcr_mask
== 0 || public);
3495 log_debug("Building sealing policy.");
3497 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
3498 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
3502 log_warning("Selected TPM2 PCRs are not initialized on this system.");
3505 if (pubkey_pcr_mask
!= 0) {
3506 TPML_PCR_SELECTION pcr_selection
;
3507 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3508 r
= tpm2_policy_authorize(c
, session
, &pcr_selection
, public, fp
, fp_size
, signature_json
, NULL
);
3513 if (hash_pcr_mask
!= 0) {
3514 TPML_PCR_SELECTION pcr_selection
;
3515 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3516 r
= tpm2_policy_pcr(c
, session
, &pcr_selection
, NULL
);
3522 r
= tpm2_policy_auth_value(c
, session
, NULL
);
3527 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3535 static const struct {
3536 TPM2_ECC_CURVE tpm2_ecc_curve_id
;
3537 int openssl_ecc_curve_id
;
3538 } tpm2_openssl_ecc_curve_table
[] = {
3539 { TPM2_ECC_NIST_P192
, NID_X9_62_prime192v1
, },
3540 { TPM2_ECC_NIST_P224
, NID_secp224r1
, },
3541 { TPM2_ECC_NIST_P256
, NID_X9_62_prime256v1
, },
3542 { TPM2_ECC_NIST_P384
, NID_secp384r1
, },
3543 { TPM2_ECC_NIST_P521
, NID_secp521r1
, },
3544 { TPM2_ECC_SM2_P256
, NID_sm2
, },
3547 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id
, TPM2_ECC_CURVE
*ret
) {
3550 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
3551 if (t
->openssl_ecc_curve_id
== openssl_ecc_curve_id
) {
3552 *ret
= t
->tpm2_ecc_curve_id
;
3556 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3557 "Openssl ECC curve id %d not supported.", openssl_ecc_curve_id
);
3560 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id
, int *ret
) {
3563 FOREACH_ARRAY(t
, tpm2_openssl_ecc_curve_table
, ELEMENTSOF(tpm2_openssl_ecc_curve_table
))
3564 if (t
->tpm2_ecc_curve_id
== tpm2_ecc_curve_id
) {
3565 *ret
= t
->openssl_ecc_curve_id
;
3569 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3570 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id
);
3573 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
3575 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
3581 const TPMT_PUBLIC
*p
= &public->publicArea
;
3583 case TPM2_ALG_ECC
: {
3585 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
3589 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
3590 return ecc_pkey_from_curve_x_y(
3598 case TPM2_ALG_RSA
: {
3599 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
3600 * zero indicates that the exponent is the default of 2^16 + 1". */
3601 uint32_t exponent
= htobe32(p
->parameters
.rsaDetail
.exponent
?: TPM2_RSA_DEFAULT_EXPONENT
);
3602 return rsa_pkey_from_n_e(
3603 p
->unique
.rsa
.buffer
,
3610 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3611 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
3615 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY
*pkey
, TPM2B_PUBLIC
*ret
) {
3621 TPMT_PUBLIC
public = {
3622 .nameAlg
= TPM2_ALG_SHA256
,
3623 .objectAttributes
= TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
,
3624 .parameters
.asymDetail
= {
3625 .symmetric
.algorithm
= TPM2_ALG_NULL
,
3626 .scheme
.scheme
= TPM2_ALG_NULL
,
3630 #if OPENSSL_VERSION_MAJOR >= 3
3631 key_id
= EVP_PKEY_get_id(pkey
);
3633 key_id
= EVP_PKEY_id(pkey
);
3638 public.type
= TPM2_ALG_ECC
;
3641 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
3642 size_t x_size
, y_size
;
3643 r
= ecc_pkey_to_curve_x_y(pkey
, &curve_id
, &x
, &x_size
, &y
, &y_size
);
3645 return log_debug_errno(r
, "Could not get ECC key curve/x/y: %m");
3647 TPM2_ECC_CURVE curve
;
3648 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
3652 public.parameters
.eccDetail
.curveID
= curve
;
3654 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
3656 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
3658 return log_debug_errno(r
, "ECC key x size %zu too large.", x_size
);
3660 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
3662 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
3664 return log_debug_errno(r
, "ECC key y size %zu too large.", y_size
);
3666 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
3670 case EVP_PKEY_RSA
: {
3671 public.type
= TPM2_ALG_RSA
;
3673 _cleanup_free_
void *n
= NULL
, *e
= NULL
;
3674 size_t n_size
, e_size
;
3675 r
= rsa_pkey_to_n_e(pkey
, &n
, &n_size
, &e
, &e_size
);
3677 return log_debug_errno(r
, "Could not get RSA key n/e: %m");
3679 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
3681 return log_debug_errno(r
, "RSA key n size %zu too large.", n_size
);
3683 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
3684 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
3686 if (sizeof(uint32_t) < e_size
)
3687 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
3688 "RSA key e size %zu too large.", e_size
);
3690 uint32_t exponent
= 0;
3691 memcpy(&exponent
, e
, e_size
);
3692 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
3693 if (exponent
== TPM2_RSA_DEFAULT_EXPONENT
)
3695 public.parameters
.rsaDetail
.exponent
= exponent
;
3700 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3701 "EVP_PKEY type %d not supported.", key_id
);
3704 *ret
= (TPM2B_PUBLIC
) {
3705 .size
= sizeof(public),
3706 .publicArea
= public,
3713 int tpm2_tpm2b_public_to_fingerprint(
3714 const TPM2B_PUBLIC
*public,
3715 void **ret_fingerprint
,
3716 size_t *ret_fingerprint_size
) {
3722 assert(ret_fingerprint
);
3723 assert(ret_fingerprint_size
);
3725 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3726 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
3730 /* Hardcode fingerprint to SHA256 */
3731 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
3733 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3737 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
3744 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3745 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
3749 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
3751 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3755 int tpm2_seal(Tpm2Context
*c
,
3756 const TPM2B_DIGEST
*policy
,
3759 size_t *ret_secret_size
,
3761 size_t *ret_blob_size
,
3762 uint16_t *ret_primary_alg
,
3764 size_t *ret_srk_buf_size
) {
3766 uint16_t primary_alg
= 0;
3771 assert(ret_secret_size
);
3773 assert(ret_blob_size
);
3775 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3776 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
3777 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3778 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3779 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3780 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3781 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3782 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3783 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3784 * LUKS2 JSON header.
3786 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3787 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3788 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3789 * binding the unlocking to the TPM2 chip. */
3791 usec_t start
= now(CLOCK_MONOTONIC
);
3793 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3794 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3795 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
3796 TPMT_PUBLIC hmac_template
= {
3797 .type
= TPM2_ALG_KEYEDHASH
,
3798 .nameAlg
= TPM2_ALG_SHA256
,
3799 .objectAttributes
= TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT
,
3800 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
3801 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
3802 .authPolicy
= policy
? *policy
: TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
),
3805 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
3806 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
3809 CLEANUP_ERASE(hmac_sensitive
);
3812 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
3817 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
3819 (void) tpm2_credit_random(c
);
3821 log_debug("Generating secret key data.");
3823 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
3825 return log_error_errno(r
, "Failed to generate secret key: %m");
3827 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
3829 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
3830 r
= tpm2_get_or_create_srk(
3832 /* session= */ NULL
,
3834 /* ret_name= */ NULL
,
3835 /* ret_qname= */ NULL
,
3840 primary_alg
= primary_public
->publicArea
.type
;
3842 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
3843 primary_alg
= TPM2_ALG_ECC
;
3845 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
3846 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
3848 return log_error_errno(r
, "Could not get legacy ECC template: %m");
3850 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
3851 primary_alg
= TPM2_ALG_RSA
;
3853 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
3855 return log_error_errno(r
, "Could not get legacy RSA template: %m");
3857 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
))
3858 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3859 "TPM does not support either ECC or RSA legacy template.");
3862 r
= tpm2_create_primary(
3864 /* session= */ NULL
,
3866 /* sensitive= */ NULL
,
3867 /* ret_public= */ NULL
,
3873 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
3874 r
= tpm2_make_encryption_session(c
, primary_handle
, &TPM2_HANDLE_NONE
, &encryption_session
);
3878 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
3879 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
3880 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
3884 _cleanup_(erase_and_freep
) void *secret
= NULL
;
3885 secret
= memdup(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
3889 log_debug("Marshalling private and public part of HMAC key.");
3891 _cleanup_free_
void *blob
= NULL
;
3892 size_t max_size
= sizeof(*private) + sizeof(*public), blob_size
= 0;
3894 blob
= malloc0(max_size
);
3898 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
3899 if (rc
!= TSS2_RC_SUCCESS
)
3900 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3901 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
3903 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
3904 if (rc
!= TSS2_RC_SUCCESS
)
3905 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3906 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3908 /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
3909 * the raw TPM handle as well as the object name. The object name is used to verify that
3910 * the key we use later is the key we expect to establish the session with.
3912 _cleanup_(Esys_Freep
) uint8_t *srk_buf
= NULL
;
3913 size_t srk_buf_size
= 0;
3915 log_debug("Serializing SRK ESYS_TR reference");
3916 rc
= sym_Esys_TR_Serialize(c
->esys_context
, primary_handle
->esys_handle
, &srk_buf
, &srk_buf_size
);
3917 if (rc
!= TSS2_RC_SUCCESS
)
3918 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3919 "Failed to serialize primary key: %s", sym_Tss2_RC_Decode(rc
));
3923 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
3927 * make a copy since we don't want the caller to understand that
3928 * ESYS allocated the pointer. It would make tracking what deallocator
3929 * to use for srk_buf in which context a PITA.
3931 void *tmp
= memdup(srk_buf
, srk_buf_size
);
3935 *ret_srk_buf
= TAKE_PTR(tmp
);
3936 *ret_srk_buf_size
= srk_buf_size
;
3939 *ret_secret
= TAKE_PTR(secret
);
3940 *ret_secret_size
= hmac_sensitive
.data
.size
;
3941 *ret_blob
= TAKE_PTR(blob
);
3942 *ret_blob_size
= blob_size
;
3944 if (ret_primary_alg
)
3945 *ret_primary_alg
= primary_alg
;
3950 #define RETRY_UNSEAL_MAX 30u
3952 int tpm2_unseal(const char *device
,
3953 uint32_t hash_pcr_mask
,
3957 uint32_t pubkey_pcr_mask
,
3958 JsonVariant
*signature
,
3960 uint16_t primary_alg
,
3963 const void *known_policy_hash
,
3964 size_t known_policy_hash_size
,
3965 const void *srk_buf
,
3966 size_t srk_buf_size
,
3968 size_t *ret_secret_size
) {
3974 assert(blob_size
> 0);
3975 assert(known_policy_hash_size
== 0 || known_policy_hash
);
3976 assert(pubkey_size
== 0 || pubkey
);
3978 assert(ret_secret_size
);
3980 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
3981 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
3985 return log_error_errno(r
, "TPM2 support is not installed.");
3987 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
3988 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
3989 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
3990 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
3991 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
3992 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
3993 * and use it to unlock the LUKS2 volume. */
3995 usec_t start
= now(CLOCK_MONOTONIC
);
3997 log_debug("Unmarshalling private part of HMAC key.");
3999 TPM2B_PRIVATE
private = {};
4001 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob
, blob_size
, &offset
, &private);
4002 if (rc
!= TSS2_RC_SUCCESS
)
4003 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4004 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
4006 log_debug("Unmarshalling public part of HMAC key.");
4008 TPM2B_PUBLIC
public = {};
4009 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob
, blob_size
, &offset
, &public);
4010 if (rc
!= TSS2_RC_SUCCESS
)
4011 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4012 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
4014 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*c
= NULL
;
4015 r
= tpm2_context_new(device
, &c
);
4019 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
4020 * so we need to handle that legacy situation. */
4021 if (pcr_bank
== UINT16_MAX
) {
4022 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
4027 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
4029 r
= tpm2_handle_new(c
, &primary_handle
);
4033 primary_handle
->flush
= false;
4035 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
4036 rc
= sym_Esys_TR_Deserialize(
4040 &primary_handle
->esys_handle
);
4041 if (rc
!= TSS2_RC_SUCCESS
)
4042 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4043 "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc
));
4044 } else if (primary_alg
!= 0) {
4045 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
4046 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
4048 return log_error_errno(r
, "Could not get legacy template: %m");
4050 r
= tpm2_create_primary(
4052 /* session= */ NULL
,
4054 /* sensitive= */ NULL
,
4055 /* ret_public= */ NULL
,
4060 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
4061 "No SRK or primary alg provided.");
4063 log_debug("Loading HMAC key into TPM.");
4066 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
4067 * gives you back a different key, the session initiation will fail. In the
4068 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
4069 * provides protections.
4071 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
4072 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
4076 TPM2B_PUBLIC pubkey_tpm2b
;
4077 _cleanup_free_
void *fp
= NULL
;
4080 r
= tpm2_tpm2b_public_from_pem(pubkey
, pubkey_size
, &pubkey_tpm2b
);
4082 return log_error_errno(r
, "Could not create TPMT_PUBLIC: %m");
4084 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
, &fp_size
);
4086 return log_error_errno(r
, "Could not get key fingerprint: %m");
4090 * if a pin is set for the seal object, use it to bind the session
4091 * key to that object. This prevents active bus interposers from
4092 * faking a TPM and seeing the unsealed value. An active interposer
4093 * could fake a TPM, satisfying the encrypted session, and just
4094 * forward everything to the *real* TPM.
4096 r
= tpm2_set_auth(c
, hmac_key
, pin
);
4100 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
4101 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
4105 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
4106 for (unsigned i
= RETRY_UNSEAL_MAX
;; i
--) {
4107 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*policy_session
= NULL
;
4108 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
4109 r
= tpm2_make_policy_session(
4117 r
= tpm2_build_sealing_policy(
4122 pubkey
? &pubkey_tpm2b
: NULL
,
4131 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
4132 * wait until the TPM2 tells us to go away. */
4133 if (known_policy_hash_size
> 0 &&
4134 memcmp_nn(policy_digest
->buffer
, policy_digest
->size
, known_policy_hash
, known_policy_hash_size
) != 0)
4135 return log_error_errno(SYNTHETIC_ERRNO(EPERM
),
4136 "Current policy digest does not match stored policy digest, cancelling "
4137 "TPM2 authentication attempt.");
4139 log_debug("Unsealing HMAC key.");
4141 rc
= sym_Esys_Unseal(
4143 hmac_key
->esys_handle
,
4144 policy_session
->esys_handle
,
4145 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
4148 if (rc
== TSS2_RC_SUCCESS
)
4150 if (rc
!= TPM2_RC_PCR_CHANGED
|| i
== 0)
4151 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4152 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc
));
4153 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i
);
4156 _cleanup_(erase_and_freep
) char *secret
= NULL
;
4157 secret
= memdup(unsealed
->buffer
, unsealed
->size
);
4158 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
4163 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
4165 *ret_secret
= TAKE_PTR(secret
);
4166 *ret_secret_size
= unsealed
->size
;
4173 int tpm2_list_devices(void) {
4175 _cleanup_(table_unrefp
) Table
*t
= NULL
;
4176 _cleanup_closedir_
DIR *d
= NULL
;
4181 return log_error_errno(r
, "TPM2 support is not installed.");
4183 t
= table_new("path", "device", "driver");
4187 d
= opendir("/sys/class/tpmrm");
4189 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
4190 if (errno
!= ENOENT
)
4194 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
4197 de
= readdir_no_dot(d
);
4201 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
4205 r
= readlink_malloc(device_path
, &device
);
4207 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
4209 driver_path
= path_join(device_path
, "driver");
4213 r
= readlink_malloc(driver_path
, &driver
);
4215 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
4218 node
= path_join("/dev", de
->d_name
);
4225 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
4226 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
4228 return table_log_add_error(r
);
4232 if (table_get_rows(t
) <= 1) {
4233 log_info("No suitable TPM2 devices found.");
4237 r
= table_print(t
, stdout
);
4239 return log_error_errno(r
, "Failed to show device table: %m");
4243 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4244 "TPM2 not supported on this build.");
4248 int tpm2_find_device_auto(
4249 int log_level
, /* log level when no device is found */
4252 _cleanup_closedir_
DIR *d
= NULL
;
4257 return log_error_errno(r
, "TPM2 support is not installed.");
4259 d
= opendir("/sys/class/tpmrm");
4261 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
,
4262 "Failed to open /sys/class/tpmrm: %m");
4263 if (errno
!= ENOENT
)
4266 _cleanup_free_
char *node
= NULL
;
4271 de
= readdir_no_dot(d
);
4276 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
4277 "More than one TPM2 (tpmrm) device found.");
4279 node
= path_join("/dev", de
->d_name
);
4285 *ret
= TAKE_PTR(node
);
4290 return log_full_errno(log_level
, SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
4292 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4293 "TPM2 not supported on this build.");
4298 static const char* tpm2_userspace_event_type_table
[_TPM2_USERSPACE_EVENT_TYPE_MAX
] = {
4299 [TPM2_EVENT_PHASE
] = "phase",
4300 [TPM2_EVENT_FILESYSTEM
] = "filesystem",
4301 [TPM2_EVENT_VOLUME_KEY
] = "volume-key",
4302 [TPM2_EVENT_MACHINE_ID
] = "machine-id",
4305 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type
, Tpm2UserspaceEventType
);
4307 const char *tpm2_userspace_log_path(void) {
4308 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/var/log/systemd/tpm2-measure.log";
4311 static int tpm2_userspace_log_open(void) {
4312 _cleanup_close_
int fd
= -EBADF
;
4317 e
= tpm2_userspace_log_path();
4318 (void) mkdir_parents(e
, 0755);
4320 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
4321 * because we use BSD file locking on it, and if anyone but root can access the file they can also
4322 * lock it, which we want to avoid. */
4323 fd
= open(e
, O_CREAT
|O_WRONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
, 0600);
4325 return log_warning_errno(errno
, "Failed to open TPM log file '%s' for writing, ignoring: %m", e
);
4327 if (flock(fd
, LOCK_EX
) < 0)
4328 return log_warning_errno(errno
, "Failed to lock TPM log file '%s', ignoring: %m", e
);
4330 if (fstat(fd
, &st
) < 0)
4331 return log_warning_errno(errno
, "Failed to fstat TPM log file '%s', ignoring: %m", e
);
4333 r
= stat_verify_regular(&st
);
4335 return log_warning_errno(r
, "TPM log file '%s' is not regular, ignoring: %m", e
);
4337 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
4338 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
4339 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
4340 * our assumed backend fs) doesn't know user xattrs. */
4341 if (st
.st_mode
& S_ISVTX
)
4342 return log_warning_errno(SYNTHETIC_ERRNO(ESTALE
), "TPM log file '%s' aborted, ignoring.", e
);
4344 if (fchmod(fd
, 0600 | S_ISVTX
) < 0)
4345 return log_warning_errno(errno
, "Failed to chmod() TPM log file '%s', ignoring: %m", e
);
4350 static int tpm2_userspace_log(
4353 const TPML_DIGEST_VALUES
*values
,
4354 Tpm2UserspaceEventType event_type
,
4355 const char *description
) {
4357 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *array
= NULL
;
4358 _cleanup_free_
char *f
= NULL
;
4363 assert(values
->count
> 0);
4365 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
4366 * Format – the JSON flavour –
4367 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
4368 * ways from it, specifically:
4370 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
4371 * through the whole logs (include firmware logs) before knowing what the next value is we should
4372 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
4373 * it in when it uses the data.
4375 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
4376 * JSON array would mean that for each appending we'd have to read the whole log file fully into
4377 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
4378 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
4380 * It should be possible to convert this format in a relatively straight-forward way into the
4381 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
4382 * determined from the full dataset.
4384 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
4385 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
4386 * timestamp which can be used to order this measurement against possibly other measurements
4387 * independently done by other subsystems on the system.
4390 if (fd
< 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
4393 for (size_t i
= 0; i
< values
->count
; i
++) {
4394 const EVP_MD
*implementation
;
4397 assert_se(a
= tpm2_hash_alg_to_string(values
->digests
[i
].hashAlg
));
4398 assert_se(implementation
= EVP_get_digestbyname(a
));
4400 r
= json_variant_append_arrayb(
4401 &array
, JSON_BUILD_OBJECT(
4402 JSON_BUILD_PAIR_STRING("hashAlg", a
),
4403 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values
->digests
[i
].digest
, EVP_MD_size(implementation
)))));
4405 return log_error_errno(r
, "Failed to append digest object to JSON array: %m");
4410 r
= sd_id128_get_boot(&boot_id
);
4412 return log_error_errno(r
, "Failed to acquire boot ID: %m");
4414 r
= json_build(&v
, JSON_BUILD_OBJECT(
4415 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index
)),
4416 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array
)),
4417 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
4418 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
4419 JSON_BUILD_PAIR_CONDITION(description
, "string", JSON_BUILD_STRING(description
)),
4420 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id
)),
4421 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME
))),
4422 JSON_BUILD_PAIR_CONDITION(event_type
>= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type
)))))));
4424 return log_error_errno(r
, "Failed to build log record JSON: %m");
4426 r
= json_variant_format(v
, JSON_FORMAT_SEQ
, &f
);
4428 return log_error_errno(r
, "Failed to format JSON: %m");
4430 if (lseek(fd
, 0, SEEK_END
) == (off_t
) -1)
4431 return log_error_errno(errno
, "Failed to seek to end of JSON log: %m");
4433 r
= loop_write(fd
, f
, SIZE_MAX
);
4435 return log_error_errno(r
, "Failed to write JSON data to log: %m");
4438 return log_error_errno(errno
, "Failed to sync JSON data: %m");
4440 /* Unset S_ISVTX again */
4441 if (fchmod(fd
, 0600) < 0)
4442 return log_warning_errno(errno
, "Failed to chmod() TPM log file, ignoring: %m");
4446 return log_error_errno(r
, "Failed to sync JSON log: %m");
4451 int tpm2_extend_bytes(
4459 Tpm2UserspaceEventType event_type
,
4460 const char *description
) {
4463 _cleanup_close_
int log_fd
= -EBADF
;
4464 TPML_DIGEST_VALUES values
= {};
4468 assert(data
|| data_size
== 0);
4469 assert(secret
|| secret_size
== 0);
4471 if (data_size
== SIZE_MAX
)
4472 data_size
= strlen(data
);
4473 if (secret_size
== SIZE_MAX
)
4474 secret_size
= strlen(secret
);
4476 if (pcr_index
>= TPM2_PCRS_MAX
)
4477 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Can't measure into unsupported PCR %u, refusing.", pcr_index
);
4479 if (strv_isempty(banks
))
4482 STRV_FOREACH(bank
, banks
) {
4483 const EVP_MD
*implementation
;
4486 assert_se(implementation
= EVP_get_digestbyname(*bank
));
4488 if (values
.count
>= ELEMENTSOF(values
.digests
))
4489 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
4491 if ((size_t) EVP_MD_size(implementation
) > sizeof(values
.digests
[values
.count
].digest
))
4492 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Hash result too large for TPM2.");
4494 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
4496 return log_error_errno(id
, "Can't map hash name to TPM2.");
4498 values
.digests
[values
.count
].hashAlg
= id
;
4500 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
4501 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
4502 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
4503 * secret for other purposes, maybe because it needs a shorter secret derived from it for
4504 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
4505 * private non-secret string instead. */
4506 if (secret_size
> 0) {
4507 if (!HMAC(implementation
, secret
, secret_size
, data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
))
4508 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to calculate HMAC of data to measure.");
4509 } else if (EVP_Digest(data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
, implementation
, NULL
) != 1)
4510 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to hash data to measure.");
4515 /* Open + lock the log file *before* we start measuring, so that noone else can come between our log
4516 * and our measurement and change either */
4517 log_fd
= tpm2_userspace_log_open();
4519 rc
= sym_Esys_PCR_Extend(
4521 ESYS_TR_PCR0
+ pcr_index
,
4526 if (rc
!= TSS2_RC_SUCCESS
)
4527 return log_error_errno(
4528 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4529 "Failed to measure into PCR %u: %s",
4531 sym_Tss2_RC_Decode(rc
));
4533 /* Now, write what we just extended to the log, too. */
4534 (void) tpm2_userspace_log(log_fd
, pcr_index
, &values
, event_type
, description
);
4537 #else /* HAVE_OPENSSL */
4538 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4543 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
4544 _cleanup_free_
char *s
= NULL
;
4546 FOREACH_PCR_IN_MASK(n
, mask
)
4547 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
4556 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
4557 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
4562 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
4563 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
4565 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
4568 r
= json_variant_new_integer(&e
, i
);
4572 r
= json_variant_append_array(&a
, e
);
4578 return json_variant_new_array(ret
, NULL
, 0);
4584 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
4588 if (!json_variant_is_array(v
))
4589 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
4591 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
4594 if (!json_variant_is_unsigned(e
))
4595 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
4597 u
= json_variant_unsigned(e
);
4598 if (u
>= TPM2_PCRS_MAX
)
4599 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR number out of range: %" PRIu64
, u
);
4601 mask
|= UINT32_C(1) << u
;
4610 int tpm2_make_luks2_json(
4612 uint32_t hash_pcr_mask
,
4616 uint32_t pubkey_pcr_mask
,
4617 uint16_t primary_alg
,
4620 const void *policy_hash
,
4621 size_t policy_hash_size
,
4624 const void *srk_buf
,
4625 size_t srk_buf_size
,
4627 JsonVariant
**ret
) {
4629 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
4630 _cleanup_free_
char *keyslot_as_string
= NULL
;
4633 assert(blob
|| blob_size
== 0);
4634 assert(policy_hash
|| policy_hash_size
== 0);
4635 assert(pubkey
|| pubkey_size
== 0);
4637 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
4640 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
4644 if (pubkey_pcr_mask
!= 0) {
4645 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
4650 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
4651 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
4652 * object should use "_" rather than "-" in field names. */
4656 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
4657 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string
))),
4658 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob
, blob_size
)),
4659 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj
)),
4660 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank
), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank
))),
4661 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg
), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg
))),
4662 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash
, policy_hash_size
)),
4663 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags
& TPM2_FLAGS_USE_PIN
)),
4664 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj
)),
4665 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey
, pubkey_size
)),
4666 JSON_BUILD_PAIR_CONDITION(salt
, "tpm2_salt", JSON_BUILD_BASE64(salt
, salt_size
)),
4667 JSON_BUILD_PAIR_CONDITION(srk_buf
, "tpm2_srk", JSON_BUILD_BASE64(srk_buf
, srk_buf_size
))));
4677 int tpm2_parse_luks2_json(
4680 uint32_t *ret_hash_pcr_mask
,
4681 uint16_t *ret_pcr_bank
,
4683 size_t *ret_pubkey_size
,
4684 uint32_t *ret_pubkey_pcr_mask
,
4685 uint16_t *ret_primary_alg
,
4687 size_t *ret_blob_size
,
4688 void **ret_policy_hash
,
4689 size_t *ret_policy_hash_size
,
4691 size_t *ret_salt_size
,
4693 size_t *ret_srk_buf_size
,
4694 TPM2Flags
*ret_flags
) {
4696 _cleanup_free_
void *blob
= NULL
, *policy_hash
= NULL
, *pubkey
= NULL
, *salt
= NULL
, *srk_buf
= NULL
;
4697 size_t blob_size
= 0, policy_hash_size
= 0, pubkey_size
= 0, salt_size
= 0, srk_buf_size
= 0;
4698 uint32_t hash_pcr_mask
= 0, pubkey_pcr_mask
= 0;
4699 uint16_t primary_alg
= TPM2_ALG_ECC
; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
4700 uint16_t pcr_bank
= UINT16_MAX
; /* default: pick automatically */
4701 int r
, keyslot
= -1;
4702 TPM2Flags flags
= 0;
4708 keyslot
= cryptsetup_get_keyslot_from_token(v
);
4710 /* Return a recognizable error when parsing this field, so that callers can handle parsing
4711 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
4713 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4718 w
= json_variant_by_key(v
, "tpm2-pcrs");
4720 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
4722 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
4724 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
4726 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4728 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
4730 /* The PCR bank field is optional */
4732 if (!json_variant_is_string(w
))
4733 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
4735 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
4737 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
4742 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4743 * the algorithm was hardcoded to ECC. */
4744 w
= json_variant_by_key(v
, "tpm2-primary-alg");
4746 /* The primary key algorithm is optional */
4748 if (!json_variant_is_string(w
))
4749 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
4751 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
4753 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
4758 w
= json_variant_by_key(v
, "tpm2-blob");
4760 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
4762 r
= json_variant_unbase64(w
, &blob
, &blob_size
);
4764 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
4766 w
= json_variant_by_key(v
, "tpm2-policy-hash");
4768 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4770 r
= json_variant_unhex(w
, &policy_hash
, &policy_hash_size
);
4772 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
4774 w
= json_variant_by_key(v
, "tpm2-pin");
4776 if (!json_variant_is_boolean(w
))
4777 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
4779 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
4782 w
= json_variant_by_key(v
, "tpm2_salt");
4784 r
= json_variant_unbase64(w
, &salt
, &salt_size
);
4786 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
4789 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
4791 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
4796 w
= json_variant_by_key(v
, "tpm2_pubkey");
4798 r
= json_variant_unbase64(w
, &pubkey
, &pubkey_size
);
4800 return log_debug_errno(r
, "Failed to decode PCR public key.");
4801 } else if (pubkey_pcr_mask
!= 0)
4802 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4804 w
= json_variant_by_key(v
, "tpm2_srk");
4806 r
= json_variant_unbase64(w
, &srk_buf
, &srk_buf_size
);
4808 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
4812 *ret_keyslot
= keyslot
;
4813 if (ret_hash_pcr_mask
)
4814 *ret_hash_pcr_mask
= hash_pcr_mask
;
4816 *ret_pcr_bank
= pcr_bank
;
4818 *ret_pubkey
= TAKE_PTR(pubkey
);
4819 if (ret_pubkey_size
)
4820 *ret_pubkey_size
= pubkey_size
;
4821 if (ret_pubkey_pcr_mask
)
4822 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
4823 if (ret_primary_alg
)
4824 *ret_primary_alg
= primary_alg
;
4826 *ret_blob
= TAKE_PTR(blob
);
4828 *ret_blob_size
= blob_size
;
4829 if (ret_policy_hash
)
4830 *ret_policy_hash
= TAKE_PTR(policy_hash
);
4831 if (ret_policy_hash_size
)
4832 *ret_policy_hash_size
= policy_hash_size
;
4834 *ret_salt
= TAKE_PTR(salt
);
4836 *ret_salt_size
= salt_size
;
4840 *ret_srk_buf
= TAKE_PTR(srk_buf
);
4841 if (ret_srk_buf_size
)
4842 *ret_srk_buf_size
= srk_buf_size
;
4847 int tpm2_hash_alg_to_size(uint16_t alg
) {
4851 case TPM2_ALG_SHA256
:
4853 case TPM2_ALG_SHA384
:
4855 case TPM2_ALG_SHA512
:
4858 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
4862 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
4866 case TPM2_ALG_SHA256
:
4868 case TPM2_ALG_SHA384
:
4870 case TPM2_ALG_SHA512
:
4873 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
4878 int tpm2_hash_alg_from_string(const char *alg
) {
4879 if (strcaseeq_ptr(alg
, "sha1"))
4880 return TPM2_ALG_SHA1
;
4881 if (strcaseeq_ptr(alg
, "sha256"))
4882 return TPM2_ALG_SHA256
;
4883 if (strcaseeq_ptr(alg
, "sha384"))
4884 return TPM2_ALG_SHA384
;
4885 if (strcaseeq_ptr(alg
, "sha512"))
4886 return TPM2_ALG_SHA512
;
4887 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm name '%s'", alg
);
4890 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
4897 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
4902 int tpm2_asym_alg_from_string(const char *alg
) {
4903 if (strcaseeq_ptr(alg
, "ecc"))
4904 return TPM2_ALG_ECC
;
4905 if (strcaseeq_ptr(alg
, "rsa"))
4906 return TPM2_ALG_RSA
;
4907 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown asymmetric algorithm name '%s'", alg
);
4910 Tpm2Support
tpm2_support(void) {
4911 Tpm2Support support
= TPM2_SUPPORT_NONE
;
4914 if (detect_container() <= 0) {
4915 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
4916 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
4917 * let's assume containers never have a TPM, at least for now. */
4919 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
4922 log_debug_errno(r
, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
4923 } else if (r
== 0) /* populated! */
4924 support
|= TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_DRIVER
;
4926 /* If the directory exists but is empty, we know the subsystem is enabled but no
4927 * driver has been loaded yet. */
4928 support
|= TPM2_SUPPORT_SUBSYSTEM
;
4932 support
|= TPM2_SUPPORT_FIRMWARE
;
4935 support
|= TPM2_SUPPORT_SYSTEM
;
4939 support
|= TPM2_SUPPORT_LIBRARIES
;
4946 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
4947 TPMI_ALG_HASH default_hash
= 0;
4948 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
4950 default_hash
= v
->hash
;
4954 if (default_hash
!= 0)
4955 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
4957 v
->hash
= default_hash
;
4961 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
4963 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
4964 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
4965 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
4967 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
4968 * tpm2_parse_pcr_argument_append(). */
4969 int tpm2_parse_pcr_argument(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
4974 assert(ret_pcr_values
);
4975 assert(ret_n_pcr_values
);
4977 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
4978 size_t n_pcr_values
= 0;
4979 r
= tpm2_pcr_values_from_string(arg
, &pcr_values
, &n_pcr_values
);
4983 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
4985 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
4987 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
4988 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
4990 *ret_pcr_values
= TAKE_PTR(pcr_values
);
4991 *ret_n_pcr_values
= n_pcr_values
;
4995 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
4999 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
5000 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
5003 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
5004 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
5005 * algorithm check applied again (in case either the previous or current array had no default hash
5006 * algorithm), and then the resulting array is sorted and rechecked for validity. */
5007 int tpm2_parse_pcr_argument_append(const char *arg
, Tpm2PCRValue
**pcr_values
, size_t *n_pcr_values
) {
5013 assert(n_pcr_values
);
5015 _cleanup_free_ Tpm2PCRValue
*more_pcr_values
= NULL
;
5016 size_t n_more_pcr_values
;
5017 r
= tpm2_parse_pcr_argument(arg
, &more_pcr_values
, &n_more_pcr_values
);
5021 /* If we got previous values, append them. */
5022 if (*pcr_values
&& !GREEDY_REALLOC_APPEND(more_pcr_values
, n_more_pcr_values
, *pcr_values
, *n_pcr_values
))
5025 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values
, n_more_pcr_values
);
5027 tpm2_sort_pcr_values(more_pcr_values
, n_more_pcr_values
);
5029 if (!tpm2_pcr_values_valid(more_pcr_values
, n_more_pcr_values
))
5030 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
5032 SWAP_TWO(*pcr_values
, more_pcr_values
);
5033 *n_pcr_values
= n_more_pcr_values
;
5037 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
5041 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
5042 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
5043 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
5044 * UINT32_MAX, and or-ing the mask otherwise. */
5045 int tpm2_parse_pcr_argument_to_mask(const char *arg
, uint32_t *ret_mask
) {
5047 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
5048 size_t n_pcr_values
;
5054 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
5058 if (n_pcr_values
== 0) {
5059 /* This retains the previous behavior of clearing the mask if the arg is empty */
5065 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
5067 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
5070 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
5073 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
5075 return log_error_errno(r
, "Could not get pcr values mask: %m");
5077 if (*ret_mask
== UINT32_MAX
)
5078 *ret_mask
= new_mask
;
5080 *ret_mask
|= new_mask
;
5084 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
5088 int tpm2_load_pcr_signature(const char *path
, JsonVariant
**ret
) {
5089 _cleanup_strv_free_
char **search
= NULL
;
5090 _cleanup_free_
char *discovered_path
= NULL
;
5091 _cleanup_fclose_
FILE *f
= NULL
;
5094 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
5095 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5097 search
= strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
5102 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
5103 * this case include /.extra/ in the search path, but only in this case, and if we run in the
5104 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
5106 path
= "tpm2-pcr-signature.json";
5109 if (strv_extend(&search
, "/.extra") < 0)
5113 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
5115 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
5117 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
5119 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
5124 int tpm2_load_pcr_public_key(const char *path
, void **ret_pubkey
, size_t *ret_pubkey_size
) {
5125 _cleanup_free_
char *discovered_path
= NULL
;
5126 _cleanup_fclose_
FILE *f
= NULL
;
5129 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
5130 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5133 path
= "tpm2-pcr-public-key.pem";
5135 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
5137 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
5139 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
5141 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
5146 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
5149 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
5150 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
5151 * I found the wikipedia entry relevant and it contains links to
5153 * - https://en.wikipedia.org/wiki/PBKDF2
5154 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
5156 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
5160 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
5162 uint8_t _cleanup_(erase_and_freep
) *buffer
= NULL
;
5163 uint8_t u
[SHA256_DIGEST_SIZE
];
5165 /* To keep this simple, since derived KeyLen (dkLen in docs)
5166 * Is the same as the hash output, we don't need multiple
5167 * blocks. Part of the algorithm is to add the block count
5168 * in, but this can be hardcoded to 1.
5170 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
5173 assert (saltlen
> 0);
5174 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
5175 assert (passlen
> 0);
5178 * Build a buffer of salt + block_cnt and hmac_sha256 it we
5179 * do this as we don't have a context builder for HMAC_SHA256.
5181 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
5185 memcpy(buffer
, salt
, saltlen
);
5186 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
5188 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
5190 /* dk needs to be an unmodified u as u gets modified in the loop */
5191 memcpy(ret_key
, u
, SHA256_DIGEST_SIZE
);
5192 uint8_t *dk
= ret_key
;
5194 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
5195 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
5197 for (size_t j
=0; j
< sizeof(u
); j
++)
5204 static const char* const tpm2_pcr_index_table
[_TPM2_PCR_INDEX_MAX_DEFINED
] = {
5205 [TPM2_PCR_PLATFORM_CODE
] = "platform-code",
5206 [TPM2_PCR_PLATFORM_CONFIG
] = "platform-config",
5207 [TPM2_PCR_EXTERNAL_CODE
] = "external-code",
5208 [TPM2_PCR_EXTERNAL_CONFIG
] = "external-config",
5209 [TPM2_PCR_BOOT_LOADER_CODE
] = "boot-loader-code",
5210 [TPM2_PCR_BOOT_LOADER_CONFIG
] = "boot-loader-config",
5211 [TPM2_PCR_HOST_PLATFORM
] = "host-platform",
5212 [TPM2_PCR_SECURE_BOOT_POLICY
] = "secure-boot-policy",
5213 [TPM2_PCR_KERNEL_INITRD
] = "kernel-initrd",
5214 [TPM2_PCR_IMA
] = "ima",
5215 [TPM2_PCR_KERNEL_BOOT
] = "kernel-boot",
5216 [TPM2_PCR_KERNEL_CONFIG
] = "kernel-config",
5217 [TPM2_PCR_SYSEXTS
] = "sysexts",
5218 [TPM2_PCR_SHIM_POLICY
] = "shim-policy",
5219 [TPM2_PCR_SYSTEM_IDENTITY
] = "system-identity",
5220 [TPM2_PCR_DEBUG
] = "debug",
5221 [TPM2_PCR_APPLICATION_SUPPORT
] = "application-support",
5224 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index
, int, TPM2_PCRS_MAX
- 1);
5225 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index
, int);