1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
5 #include "cryptsetup-util.h"
6 #include "dirent-util.h"
7 #include "dlfcn-util.h"
9 #include "extract-word.h"
12 #include "format-table.h"
14 #include "hexdecoct.h"
16 #include "initrd-util.h"
17 #include "lock-util.h"
19 #include "logarithm.h"
20 #include "memory-util.h"
21 #include "nulstr-util.h"
22 #include "parse-util.h"
23 #include "random-util.h"
25 #include "sort-util.h"
26 #include "stat-util.h"
27 #include "string-table.h"
28 #include "time-util.h"
29 #include "tpm2-util.h"
33 static void *libtss2_esys_dl
= NULL
;
34 static void *libtss2_rc_dl
= NULL
;
35 static void *libtss2_mu_dl
= NULL
;
37 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
;
38 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
;
39 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
;
40 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
;
41 static void (*sym_Esys_Finalize
)(ESYS_CONTEXT
**context
) = NULL
;
42 static TSS2_RC (*sym_Esys_FlushContext
)(ESYS_CONTEXT
*esysContext
, ESYS_TR flushHandle
) = NULL
;
43 static void (*sym_Esys_Free
)(void *ptr
) = NULL
;
44 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
;
45 static TSS2_RC (*sym_Esys_GetRandom
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, UINT16 bytesRequested
, TPM2B_DIGEST
**randomBytes
) = NULL
;
46 static TSS2_RC (*sym_Esys_Initialize
)(ESYS_CONTEXT
**esys_context
, TSS2_TCTI_CONTEXT
*tcti
, TSS2_ABI_VERSION
*abiVersion
) = NULL
;
47 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
;
48 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
;
49 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
;
50 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
;
51 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
;
52 static TSS2_RC (*sym_Esys_PolicyAuthValue
)(ESYS_CONTEXT
*esysContext
, ESYS_TR policySession
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
) = NULL
;
53 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
;
54 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
;
55 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
;
56 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
;
57 static TSS2_RC (*sym_Esys_Startup
)(ESYS_CONTEXT
*esysContext
, TPM2_SU startupType
) = NULL
;
58 static TSS2_RC (*sym_Esys_TestParms
)(ESYS_CONTEXT
*esysContext
, ESYS_TR shandle1
, ESYS_TR shandle2
, ESYS_TR shandle3
, const TPMT_PUBLIC_PARMS
*parameters
) = NULL
;
59 static TSS2_RC (*sym_Esys_TR_Close
)(ESYS_CONTEXT
*esys_context
, ESYS_TR
*rsrc_handle
) = NULL
;
60 static TSS2_RC (*sym_Esys_TR_Deserialize
)(ESYS_CONTEXT
*esys_context
, uint8_t const *buffer
, size_t buffer_size
, ESYS_TR
*esys_handle
) = NULL
;
61 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
;
62 static TSS2_RC (*sym_Esys_TR_GetName
)(ESYS_CONTEXT
*esysContext
, ESYS_TR handle
, TPM2B_NAME
**name
) = NULL
;
63 static TSS2_RC (*sym_Esys_TR_Serialize
)(ESYS_CONTEXT
*esys_context
, ESYS_TR object
, uint8_t **buffer
, size_t *buffer_size
) = NULL
;
64 static TSS2_RC (*sym_Esys_TR_SetAuth
)(ESYS_CONTEXT
*esysContext
, ESYS_TR handle
, TPM2B_AUTH
const *authValue
) = NULL
;
65 static TSS2_RC (*sym_Esys_TRSess_GetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION
*flags
) = NULL
;
66 static TSS2_RC (*sym_Esys_TRSess_SetAttributes
)(ESYS_CONTEXT
*esysContext
, ESYS_TR session
, TPMA_SESSION flags
, TPMA_SESSION mask
) = NULL
;
67 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
;
68 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
;
70 static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal
)(TPM2_CC src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
71 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal
)(TPM2B_PRIVATE
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
72 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PRIVATE
*dest
) = NULL
;
73 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal
)(TPM2B_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
74 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal
)(uint8_t const buffer
[], size_t buffer_size
, size_t *offset
, TPM2B_PUBLIC
*dest
) = NULL
;
75 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
;
76 static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal
)(TPMT_HA
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
77 static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal
)(TPMT_PUBLIC
const *src
, uint8_t buffer
[], size_t buffer_size
, size_t *offset
) = NULL
;
79 static const char* (*sym_Tss2_RC_Decode
)(TSS2_RC rc
) = NULL
;
81 int dlopen_tpm2(void) {
84 r
= dlopen_many_sym_or_warn(
85 &libtss2_esys_dl
, "libtss2-esys.so.0", LOG_DEBUG
,
86 DLSYM_ARG(Esys_Create
),
87 DLSYM_ARG(Esys_CreateLoaded
),
88 DLSYM_ARG(Esys_CreatePrimary
),
89 DLSYM_ARG(Esys_EvictControl
),
90 DLSYM_ARG(Esys_Finalize
),
91 DLSYM_ARG(Esys_FlushContext
),
93 DLSYM_ARG(Esys_GetCapability
),
94 DLSYM_ARG(Esys_GetRandom
),
95 DLSYM_ARG(Esys_Initialize
),
97 DLSYM_ARG(Esys_LoadExternal
),
98 DLSYM_ARG(Esys_PCR_Extend
),
99 DLSYM_ARG(Esys_PCR_Read
),
100 DLSYM_ARG(Esys_PolicyAuthorize
),
101 DLSYM_ARG(Esys_PolicyAuthValue
),
102 DLSYM_ARG(Esys_PolicyGetDigest
),
103 DLSYM_ARG(Esys_PolicyPCR
),
104 DLSYM_ARG(Esys_ReadPublic
),
105 DLSYM_ARG(Esys_StartAuthSession
),
106 DLSYM_ARG(Esys_Startup
),
107 DLSYM_ARG(Esys_TestParms
),
108 DLSYM_ARG(Esys_TR_Close
),
109 DLSYM_ARG(Esys_TR_Deserialize
),
110 DLSYM_ARG(Esys_TR_FromTPMPublic
),
111 DLSYM_ARG(Esys_TR_GetName
),
112 DLSYM_ARG(Esys_TR_Serialize
),
113 DLSYM_ARG(Esys_TR_SetAuth
),
114 DLSYM_ARG(Esys_TRSess_GetAttributes
),
115 DLSYM_ARG(Esys_TRSess_SetAttributes
),
116 DLSYM_ARG(Esys_Unseal
),
117 DLSYM_ARG(Esys_VerifySignature
));
121 r
= dlopen_many_sym_or_warn(
122 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
123 DLSYM_ARG(Tss2_RC_Decode
));
127 return dlopen_many_sym_or_warn(
128 &libtss2_mu_dl
, "libtss2-mu.so.0", LOG_DEBUG
,
129 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal
),
130 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal
),
131 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal
),
132 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal
),
133 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal
),
134 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal
),
135 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal
),
136 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal
));
139 static inline void Esys_Freep(void *p
) {
141 sym_Esys_Free(*(void**) p
);
144 /* Get a specific TPM capability (or capabilities).
146 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
147 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
148 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
149 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
151 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
152 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
153 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
154 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
155 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
156 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
157 * capability category may have more specific requirements than described here; see the spec for exact
159 static int tpm2_get_capability(
164 TPMU_CAPABILITIES
*ret_capability_data
) {
166 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
172 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
173 capability
, property
, count
);
175 rc
= sym_Esys_GetCapability(
185 if (rc
!= TSS2_RC_SUCCESS
)
186 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
187 "Failed to get TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
": %s",
188 capability
, property
, sym_Tss2_RC_Decode(rc
));
190 if (capabilities
->capability
!= capability
)
191 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
192 "TPM provided wrong capability: 0x%04" PRIx32
" instead of 0x%04" PRIx32
".",
193 capabilities
->capability
, capability
);
195 if (ret_capability_data
)
196 *ret_capability_data
= capabilities
->data
;
198 return more
== TPM2_YES
;
201 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
203 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
204 TPMU_CAPABILITIES capability
;
209 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
210 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
211 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
212 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
213 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
214 * changed while we are performing some operation, it's reasonable to assume it will break us even if
215 * we don't cache the algorithms, thus they should be "safe" to cache. */
216 TPM2_ALG_ID current_alg
= TPM2_ALG_FIRST
;
218 r
= tpm2_get_capability(
221 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
227 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
229 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
230 * there are no more. */
231 assert(algorithms
.count
> 0);
233 if (!GREEDY_REALLOC_APPEND(
234 c
->capability_algorithms
,
235 c
->n_capability_algorithms
,
236 algorithms
.algProperties
,
243 /* Set current_alg to alg id after last alg id the TPM provided */
244 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
247 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
248 * while running, but that would be crazy, so let's hope it is not possible. */
249 TPM2_CC current_cc
= TPM2_CC_FIRST
;
251 r
= tpm2_get_capability(
260 TPML_CCA commands
= capability
.command
;
262 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
263 * there are no more. */
264 assert(commands
.count
> 0);
266 if (!GREEDY_REALLOC_APPEND(
267 c
->capability_commands
,
268 c
->n_capability_commands
,
269 commands
.commandAttributes
,
276 /* Set current_cc to index after last cc the TPM provided */
277 current_cc
= TPMA_CC_TO_TPM2_CC(commands
.commandAttributes
[commands
.count
- 1]) + 1;
280 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
281 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
282 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
283 * safely assume the TPM PCR allocation will not change while we are using it. */
284 r
= tpm2_get_capability(
293 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
294 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
295 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
296 * this command with the full PCR allocation and moreData will be NO." */
297 log_warning("TPM bug: reported multiple PCR sets; using only first set.");
298 c
->capability_pcrs
= capability
.assignedPCR
;
303 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
304 * TPMA_ALGORITHM is provided, otherwise false. */
305 static bool tpm2_get_capability_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
, TPMA_ALGORITHM
*ret
) {
308 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
309 if (alg_prop
->alg
== alg
) {
311 *ret
= alg_prop
->algProperties
;
315 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
322 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
323 return tpm2_get_capability_alg(c
, alg
, NULL
);
326 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
327 * otherwise false. */
328 static bool tpm2_get_capability_command(Tpm2Context
*c
, TPM2_CC command
, TPMA_CC
*ret
) {
331 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
332 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
338 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
345 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
346 return tpm2_get_capability_command(c
, command
, NULL
);
349 /* Returns 1 if the TPM supports the ECC curve, 0 if not, or < 0 for any error. */
350 static int tpm2_supports_ecc_curve(Tpm2Context
*c
, TPM2_ECC_CURVE curve
) {
351 TPMU_CAPABILITIES capability
;
354 /* The spec explicitly states the TPM2_ECC_CURVE should be cast to uint32_t. */
355 r
= tpm2_get_capability(c
, TPM2_CAP_ECC_CURVES
, (uint32_t) curve
, 1, &capability
);
359 TPML_ECC_CURVE eccCurves
= capability
.eccCurves
;
360 if (eccCurves
.count
== 0 || eccCurves
.eccCurves
[0] != curve
) {
361 log_debug("TPM does not support ECC curve 0x%02" PRIx16
".", curve
);
368 /* Query the TPM for populated handles.
370 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
371 * contain only populated handle addresses (which might not include the requested handle). The number of
372 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
373 * range (i.e. handle & 0xff000000).
375 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
376 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
377 static int tpm2_get_capability_handles(
381 TPM2_HANDLE
**ret_handles
,
382 size_t *ret_n_handles
) {
384 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
385 size_t n_handles
= 0;
386 TPM2_HANDLE current
= start
;
391 assert(ret_n_handles
);
394 TPMU_CAPABILITIES capability
;
395 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
399 TPML_HANDLE handle_list
= capability
.handles
;
400 if (handle_list
.count
== 0)
403 assert(handle_list
.count
<= max
);
405 if (n_handles
> SIZE_MAX
- handle_list
.count
)
408 if (!GREEDY_REALLOC(handles
, n_handles
+ handle_list
.count
))
411 memcpy_safe(&handles
[n_handles
], handle_list
.handle
, sizeof(handles
[0]) * handle_list
.count
);
413 max
-= handle_list
.count
;
414 n_handles
+= handle_list
.count
;
416 /* Update current to the handle index after the last handle in the list. */
417 current
= handles
[n_handles
- 1] + 1;
420 /* No more handles in this range. */
424 *ret_handles
= TAKE_PTR(handles
);
425 *ret_n_handles
= n_handles
;
430 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
431 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
433 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
434 static int tpm2_get_capability_handle(Tpm2Context
*c
, TPM2_HANDLE handle
) {
435 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
436 size_t n_handles
= 0;
439 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
443 return n_handles
== 0 ? false : handles
[0] == handle
;
446 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
447 bool tpm2_test_parms(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, const TPMU_PUBLIC_PARMS
*parms
) {
453 TPMT_PUBLIC_PARMS parameters
= {
455 .parameters
= *parms
,
458 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
459 if (rc
!= TSS2_RC_SUCCESS
)
460 /* The spec says if the parms are not supported the TPM returns "...the appropriate
461 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
462 * unmarshaling errors, instead of checking for them all here, let's just assume any error
463 * indicates unsupported parms, and log the specific error text. */
464 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc
));
466 return rc
== TSS2_RC_SUCCESS
;
469 static inline bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
473 return tpm2_test_parms(c
, public->type
, &public->parameters
);
476 static inline bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
480 TPMU_PUBLIC_PARMS parms
= {
481 .symDetail
.sym
= *parameters
,
484 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
487 static inline bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
491 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
492 * functionally identical. */
493 TPMT_SYM_DEF_OBJECT object
= {
494 .algorithm
= parameters
->algorithm
,
495 .keyBits
= parameters
->keyBits
,
496 .mode
= parameters
->mode
,
499 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
502 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
507 sym_Esys_Finalize(&c
->esys_context
);
509 c
->tcti_context
= mfree(c
->tcti_context
);
510 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
512 c
->capability_algorithms
= mfree(c
->capability_algorithms
);
513 c
->capability_commands
= mfree(c
->capability_commands
);
518 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
520 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
521 .algorithm
= TPM2_ALG_AES
,
523 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
526 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
527 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
533 context
= new(Tpm2Context
, 1);
537 *context
= (Tpm2Context
) {
543 return log_error_errno(r
, "TPM2 support not installed: %m");
546 device
= secure_getenv("SYSTEMD_TPM2_DEVICE");
548 /* Setting the env var to an empty string forces tpm2-tss' own device picking
549 * logic to be used. */
550 device
= empty_to_null(device
);
552 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
553 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
554 * might be used and we really don't want that, since it is a system service and that creates
555 * various ordering issues/deadlocks during early boot. */
556 device
= "device:/dev/tpmrm0";
560 const char *param
, *driver
, *fn
;
561 const TSS2_TCTI_INFO
* info
;
562 TSS2_TCTI_INFO_FUNC func
;
565 param
= strchr(device
, ':');
567 /* Syntax #1: Pair of driver string and arbitrary parameter */
568 driver
= strndupa_safe(device
, param
- device
);
570 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
573 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
574 /* Syntax #2: TPM device node */
578 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
580 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
582 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
584 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
585 if (!filename_is_valid(fn
))
586 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name '%s' not valid, refusing.", driver
);
588 context
->tcti_dl
= dlopen(fn
, RTLD_NOW
);
589 if (!context
->tcti_dl
)
590 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to load %s: %s", fn
, dlerror());
592 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
594 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
595 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
600 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
602 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
604 rc
= info
->init(NULL
, &sz
, NULL
);
605 if (rc
!= TPM2_RC_SUCCESS
)
606 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
607 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
609 context
->tcti_context
= malloc0(sz
);
610 if (!context
->tcti_context
)
613 rc
= info
->init(context
->tcti_context
, &sz
, param
);
614 if (rc
!= TPM2_RC_SUCCESS
)
615 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
616 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc
));
619 rc
= sym_Esys_Initialize(&context
->esys_context
, context
->tcti_context
, NULL
);
620 if (rc
!= TSS2_RC_SUCCESS
)
621 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
622 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc
));
624 rc
= sym_Esys_Startup(context
->esys_context
, TPM2_SU_CLEAR
);
625 if (rc
== TPM2_RC_INITIALIZE
)
626 log_debug("TPM already started up.");
627 else if (rc
== TSS2_RC_SUCCESS
)
628 log_debug("TPM successfully started up.");
630 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
631 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
633 r
= tpm2_cache_capabilities(context
);
637 /* We require AES and CFB support for session encryption. */
638 if (!tpm2_supports_alg(context
, TPM2_ALG_AES
))
639 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES.");
641 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
642 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support CFB.");
644 if (!tpm2_supports_tpmt_sym_def(context
, &SESSION_TEMPLATE_SYM_AES_128_CFB
))
645 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support AES-128-CFB.");
647 *ret_context
= TAKE_PTR(context
);
652 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
655 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
658 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
659 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
660 * as removing its corresponding handle from the actual TPM. */
662 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
664 rc
= sym_Esys_TR_Close(esys_context
, &esys_handle
);
665 if (rc
!= TSS2_RC_SUCCESS
) /* We ignore failures here (besides debug logging), since this is called
666 * in error paths, where we cannot do anything about failures anymore. And
667 * when it is called in successful codepaths by this time we already did
668 * what we wanted to do, and got the results we wanted so there's no
669 * reason to make this fail more loudly than necessary. */
670 log_debug("Failed to %s TPM handle, ignoring: %s", flush
? "flush" : "close", sym_Tss2_RC_Decode(rc
));
673 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
677 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
679 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
681 return mfree(handle
);
684 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
685 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
689 handle
= new(Tpm2Handle
, 1);
693 *handle
= (Tpm2Handle
) {
694 .tpm2_context
= tpm2_context_ref(context
),
695 .esys_handle
= ESYS_TR_NONE
,
699 *ret_handle
= TAKE_PTR(handle
);
704 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the TPM2_HANDLE address
705 * provided. This should be used only for persistent, transient, or NV handles. Returns 1 on success, 0 if
706 * the requested handle is not present in the TPM, or < 0 on error. */
707 static int tpm2_esys_handle_from_tpm_handle(
709 const Tpm2Handle
*session
,
710 TPM2_HANDLE tpm_handle
,
711 Tpm2Handle
**ret_handle
) {
717 assert(tpm_handle
> 0);
720 /* Let's restrict this, at least for now, to allow only some handle types. */
721 switch (TPM2_HANDLE_TYPE(tpm_handle
)) {
722 case TPM2_HT_PERSISTENT
:
723 case TPM2_HT_NV_INDEX
:
724 case TPM2_HT_TRANSIENT
:
727 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
728 "Refusing to create ESYS handle for PCR handle 0x%08" PRIx32
".",
730 case TPM2_HT_HMAC_SESSION
:
731 case TPM2_HT_POLICY_SESSION
:
732 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
733 "Refusing to create ESYS handle for session handle 0x%08" PRIx32
".",
735 case TPM2_HT_PERMANENT
: /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
736 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
737 "Refusing to create ESYS handle for permanent handle 0x%08" PRIx32
".",
740 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
741 "Refusing to create ESYS handle for unknown handle 0x%08" PRIx32
".",
745 r
= tpm2_get_capability_handle(c
, tpm_handle
);
749 log_debug("TPM handle 0x%08" PRIx32
" not populated.", tpm_handle
);
754 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
755 r
= tpm2_handle_new(c
, &handle
);
759 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
760 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
761 handle
->flush
= false;
763 rc
= sym_Esys_TR_FromTPMPublic(
766 session
? session
->esys_handle
: ESYS_TR_NONE
,
769 &handle
->esys_handle
);
770 if (rc
!= TSS2_RC_SUCCESS
)
771 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
772 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
774 *ret_handle
= TAKE_PTR(handle
);
779 /* Copy an object in the TPM at a transient location to a persistent location.
781 * The provided transient handle must exist in the TPM in the transient range. The persistent location may be
782 * 0 or any location in the persistent range. If 0, this will try each handle in the persistent range, in
783 * ascending order, until an available one is found. If non-zero, only the requested persistent location will
786 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
787 * location(s), or < 0 on error. The persistent handle is only provided when returning 1. */
788 static int tpm2_persist_handle(
790 const Tpm2Handle
*transient_handle
,
791 const Tpm2Handle
*session
,
792 TPMI_DH_PERSISTENT persistent_location
,
793 Tpm2Handle
**ret_persistent_handle
) {
795 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
796 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
797 TPMI_DH_PERSISTENT first
= UINT32_C(0x81000000), last
= UINT32_C(0x81ffffff);
802 assert(transient_handle
);
804 /* If persistent location specified, only try that. */
805 if (persistent_location
!= 0) {
806 if (TPM2_HANDLE_TYPE(persistent_location
) != TPM2_HT_PERSISTENT
)
807 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
808 "Handle not in persistent range: 0x%x", persistent_location
);
810 first
= last
= persistent_location
;
813 for (TPMI_DH_PERSISTENT requested
= first
; requested
<= last
; requested
++) {
814 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*persistent_handle
= NULL
;
815 r
= tpm2_handle_new(c
, &persistent_handle
);
819 /* Since this is a persistent handle, don't flush it. */
820 persistent_handle
->flush
= false;
822 rc
= sym_Esys_EvictControl(
825 transient_handle
->esys_handle
,
826 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
830 &persistent_handle
->esys_handle
);
831 if (rc
== TSS2_RC_SUCCESS
) {
832 if (ret_persistent_handle
)
833 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
837 if (rc
!= TPM2_RC_NV_DEFINED
)
838 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
839 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc
));
842 if (ret_persistent_handle
)
843 *ret_persistent_handle
= NULL
;
848 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
850 static int tpm2_credit_random(Tpm2Context
*c
) {
851 size_t rps
, done
= 0;
858 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
859 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
860 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
863 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH
, F_OK
) < 0) {
865 log_debug_errno(errno
, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH
"' exists, ignoring: %m");
867 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
868 return 0; /* Already done */
871 t
= now(CLOCK_MONOTONIC
);
873 for (rps
= random_pool_size(); rps
> 0;) {
874 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
876 rc
= sym_Esys_GetRandom(
881 MIN(rps
, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
883 if (rc
!= TSS2_RC_SUCCESS
)
884 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
885 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc
));
887 if (buffer
->size
== 0)
888 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
889 "Zero-sized entropy returned from TPM.");
891 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
893 return log_error_errno(r
, "Failed wo write entropy to kernel: %m");
895 done
+= buffer
->size
;
896 rps
= LESS_BY(rps
, buffer
->size
);
899 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
901 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
903 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
908 static int tpm2_read_public(
910 const Tpm2Handle
*session
,
911 const Tpm2Handle
*handle
,
912 TPM2B_PUBLIC
**ret_public
,
913 TPM2B_NAME
**ret_name
,
914 TPM2B_NAME
**ret_qname
) {
921 rc
= sym_Esys_ReadPublic(
924 session
? session
->esys_handle
: ESYS_TR_NONE
,
930 if (rc
!= TSS2_RC_SUCCESS
)
931 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
932 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc
));
937 /* Get one of the legacy primary key templates.
939 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
940 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
941 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
942 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
943 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
945 static const TPMT_PUBLIC legacy_ecc
= {
946 .type
= TPM2_ALG_ECC
,
947 .nameAlg
= TPM2_ALG_SHA256
,
948 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
949 .parameters
.eccDetail
= {
951 .algorithm
= TPM2_ALG_AES
,
953 .mode
.aes
= TPM2_ALG_CFB
,
955 .scheme
.scheme
= TPM2_ALG_NULL
,
956 .curveID
= TPM2_ECC_NIST_P256
,
957 .kdf
.scheme
= TPM2_ALG_NULL
,
962 static const TPMT_PUBLIC legacy_rsa
= {
963 .type
= TPM2_ALG_RSA
,
964 .nameAlg
= TPM2_ALG_SHA256
,
965 .objectAttributes
= TPMA_OBJECT_RESTRICTED
|TPMA_OBJECT_DECRYPT
|TPMA_OBJECT_FIXEDTPM
|TPMA_OBJECT_FIXEDPARENT
|TPMA_OBJECT_SENSITIVEDATAORIGIN
|TPMA_OBJECT_USERWITHAUTH
,
966 .parameters
.rsaDetail
= {
968 .algorithm
= TPM2_ALG_AES
,
970 .mode
.aes
= TPM2_ALG_CFB
,
972 .scheme
.scheme
= TPM2_ALG_NULL
,
977 assert(ret_template
);
979 if (alg
== TPM2_ALG_ECC
)
980 *ret_template
= legacy_ecc
;
981 else if (alg
== TPM2_ALG_RSA
)
982 *ret_template
= legacy_rsa
;
984 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
985 "Unsupported legacy SRK alg: 0x%x", alg
);
990 /* Get a Storage Root Key (SRK) template.
992 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
993 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
994 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
995 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
998 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
999 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1001 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1002 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1003 * (see TPM2_SRK_HANDLE and tpm2_get_srk() below).
1005 * The alg must be TPM2_ALG_RSA or TPM2_ALG_ECC. Returns error if the requested template is not supported on
1006 * this TPM. Also see tpm2_get_best_srk_template() below. */
1007 static int tpm2_get_srk_template(Tpm2Context
*c
, TPMI_ALG_PUBLIC alg
, TPMT_PUBLIC
*ret_template
) {
1008 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1009 * Provisioning Guidance document, specifically:
1010 * TPMA_OBJECT_USERWITHAUTH is added.
1011 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1012 * TPMA_OBJECT_NODA is added. */
1013 TPMA_OBJECT srk_attributes
=
1014 TPMA_OBJECT_DECRYPT
|
1015 TPMA_OBJECT_FIXEDPARENT
|
1016 TPMA_OBJECT_FIXEDTPM
|
1018 TPMA_OBJECT_RESTRICTED
|
1019 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1020 TPMA_OBJECT_USERWITHAUTH
;
1022 /* The symmetric configuration is the same between ECC and RSA templates. */
1023 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1024 .algorithm
= TPM2_ALG_AES
,
1026 .mode
.aes
= TPM2_ALG_CFB
,
1029 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1031 /* From the EK Credential Profile template "L-2". */
1032 TPMT_PUBLIC srk_ecc
= {
1033 .type
= TPM2_ALG_ECC
,
1034 .nameAlg
= TPM2_ALG_SHA256
,
1035 .objectAttributes
= srk_attributes
,
1036 .parameters
.eccDetail
= {
1037 .symmetric
= srk_symmetric
,
1038 .scheme
.scheme
= TPM2_ALG_NULL
,
1039 .curveID
= TPM2_ECC_NIST_P256
,
1040 .kdf
.scheme
= TPM2_ALG_NULL
,
1044 /* From the EK Credential Profile template "L-1". */
1045 TPMT_PUBLIC srk_rsa
= {
1046 .type
= TPM2_ALG_RSA
,
1047 .nameAlg
= TPM2_ALG_SHA256
,
1048 .objectAttributes
= srk_attributes
,
1049 .parameters
.rsaDetail
= {
1050 .symmetric
= srk_symmetric
,
1051 .scheme
.scheme
= TPM2_ALG_NULL
,
1057 assert(ret_template
);
1059 if (alg
== TPM2_ALG_ECC
) {
1060 if (!tpm2_supports_alg(c
, TPM2_ALG_ECC
))
1061 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1062 "TPM does not support ECC.");
1064 if (!tpm2_supports_ecc_curve(c
, srk_ecc
.parameters
.eccDetail
.curveID
))
1065 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1066 "TPM does not support ECC-NIST-P256 curve.");
1068 if (!tpm2_supports_tpmt_public(c
, &srk_ecc
))
1069 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1070 "TPM does not support SRK ECC template L-2.");
1072 *ret_template
= srk_ecc
;
1076 if (alg
== TPM2_ALG_RSA
) {
1077 if (!tpm2_supports_alg(c
, TPM2_ALG_RSA
))
1078 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1079 "TPM does not support RSA.");
1081 if (!tpm2_supports_tpmt_public(c
, &srk_rsa
))
1082 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1083 "TPM does not support SRK RSA template L-1.");
1085 *ret_template
= srk_rsa
;
1089 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Unsupported SRK alg: 0x%x.", alg
);
1092 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1093 static int tpm2_get_best_srk_template(Tpm2Context
*c
, TPMT_PUBLIC
*ret_template
) {
1094 if (tpm2_get_srk_template(c
, TPM2_ALG_ECC
, ret_template
) >= 0 ||
1095 tpm2_get_srk_template(c
, TPM2_ALG_RSA
, ret_template
) >= 0)
1098 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1099 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1102 /* The SRK handle is defined in the Provisioning Guidance document (see above) in the table "Reserved Handles
1103 * for TPM Provisioning Fundamental Elements". The SRK is useful because it is "shared", meaning it has no
1104 * authValue nor authPolicy set, and thus may be used by anyone on the system to generate derived keys or
1105 * seal secrets. This is useful if the TPM has an auth (password) set for the 'owner hierarchy', which would
1106 * prevent users from generating primary transient keys, unless they knew the owner hierarchy auth. See
1107 * the Provisioning Guidance document for more details. */
1108 #define TPM2_SRK_HANDLE UINT32_C(0x81000001)
1110 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1111 * tpm2_get_or_create_srk() below. */
1112 static int tpm2_get_srk(
1114 const Tpm2Handle
*session
,
1115 TPM2B_PUBLIC
**ret_public
,
1116 TPM2B_NAME
**ret_name
,
1117 TPM2B_NAME
**ret_qname
,
1118 Tpm2Handle
**ret_handle
) {
1124 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
1125 r
= tpm2_esys_handle_from_tpm_handle(c
, session
, TPM2_SRK_HANDLE
, &handle
);
1128 if (r
== 0) { /* SRK not found */
1140 if (ret_public
|| ret_name
|| ret_qname
) {
1141 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
1147 *ret_handle
= TAKE_PTR(handle
);
1152 /* Get the SRK, creating one if needed. Returns 0 on success, or < 0 on error. */
1153 static int tpm2_get_or_create_srk(
1155 const Tpm2Handle
*session
,
1156 TPM2B_PUBLIC
**ret_public
,
1157 TPM2B_NAME
**ret_name
,
1158 TPM2B_NAME
**ret_qname
,
1159 Tpm2Handle
**ret_handle
) {
1163 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1169 /* No SRK, create and persist one */
1170 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
1171 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1173 return log_error_errno(r
, "Could not get best SRK template: %m");
1175 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1176 r
= tpm2_create_primary(
1180 /* sensitive= */ NULL
,
1181 /* ret_public= */ NULL
,
1186 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1187 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1188 * either case, all threads will get the persistent SRK below. */
1189 r
= tpm2_persist_handle(c
, transient_handle
, session
, TPM2_SRK_HANDLE
, /* ret_persistent_handle= */ NULL
);
1193 /* The SRK should exist now. */
1194 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1198 /* This should never happen. */
1199 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1204 /* Utility functions for TPMS_PCR_SELECTION. */
1206 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1207 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1209 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1212 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1213 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
1217 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1218 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPMS_PCR_SELECTION
*ret
) {
1221 /* This is currently hardcoded at 24 PCRs, above. */
1222 if (!TPM2_PCR_MASK_VALID(mask
))
1223 log_warning("PCR mask selections (%x) out of range, ignoring.",
1224 mask
& ~((uint32_t)TPM2_PCRS_MASK
));
1226 *ret
= (TPMS_PCR_SELECTION
){
1228 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1229 .pcrSelect
[0] = mask
& 0xff,
1230 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1231 .pcrSelect
[2] = (mask
>> 16) & 0xff,
1235 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1236 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1239 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1242 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1245 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
1248 /* Add all PCR selections in the mask. */
1249 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1250 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 1);
1253 /* Remove all PCR selections in the mask. */
1254 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
) {
1255 tpm2_tpms_pcr_selection_update_mask(s
, mask
, 0);
1258 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1259 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1262 assert(a
->hash
== b
->hash
);
1264 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1267 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1268 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION
*a
, const TPMS_PCR_SELECTION
*b
) {
1271 assert(a
->hash
== b
->hash
);
1273 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
1276 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1277 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION
*a
, TPMS_PCR_SELECTION
*b
) {
1281 tpm2_tpms_pcr_selection_add(a
, b
);
1282 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
1285 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1286 _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, UNIQ)
1287 #define _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, uniq) \
1288 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1290 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1291 UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ)
1292 #define UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, uniq) \
1293 for (TPML_PCR_SELECTION *UNIQ_T(_tpml, uniq) = (TPML_PCR_SELECTION*)(tpml); \
1294 UNIQ_T(_tpml, uniq); UNIQ_T(_tpml, uniq) = NULL) \
1295 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, UNIQ_T(_tpml, uniq))
1296 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1297 for (TPMS_PCR_SELECTION *tpms = tpml->pcrSelections; \
1298 (uint32_t)(tpms - tpml->pcrSelections) < tpml->count; \
1301 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1302 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1303 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1305 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1308 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1310 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1314 return strjoin(algstr
, "(", mask
, ")");
1317 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1320 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1323 /* Utility functions for TPML_PCR_SELECTION. */
1325 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1326 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION
*l
, uint32_t index
) {
1328 assert(l
->count
<= sizeof(l
->pcrSelections
));
1329 assert(index
< l
->count
);
1331 size_t s
= l
->count
- (index
+ 1);
1332 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
1336 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1337 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1338 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1339 static TPMS_PCR_SELECTION
*tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1340 TPML_PCR_SELECTION
*l
,
1341 TPMI_ALG_HASH hash_alg
) {
1345 TPMS_PCR_SELECTION
*selection
= NULL
;
1346 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1347 if (s
->hash
== hash_alg
) {
1355 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1356 for (uint32_t i
= l
->count
- 1; i
> 0; i
--) {
1357 TPMS_PCR_SELECTION
*s
= &l
->pcrSelections
[i
];
1362 if (s
->hash
== hash_alg
) {
1363 tpm2_tpms_pcr_selection_move(selection
, s
);
1364 tpm2_tpml_pcr_selection_remove_index(l
, i
);
1371 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1372 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION
*l
, TPMI_ALG_HASH hash_alg
) {
1375 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1376 * are multiple entries with the requested hash alg. */
1377 TPML_PCR_SELECTION lcopy
= *l
;
1379 TPMS_PCR_SELECTION
*s
;
1380 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1384 return tpm2_tpms_pcr_selection_to_mask(s
);
1387 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1388 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask
, TPMI_ALG_HASH hash_alg
, TPML_PCR_SELECTION
*ret
) {
1391 TPMS_PCR_SELECTION s
;
1392 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1394 *ret
= (TPML_PCR_SELECTION
){
1396 .pcrSelections
[0] = s
,
1400 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1401 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION
*l
) {
1402 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1403 /* This removes all duplicates for s->hash. */
1404 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
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
> sizeof(l
->pcrSelections
)));
1426 /* If full, the cleanup should result in at least one available entry. */
1427 if (l
->count
== sizeof(l
->pcrSelections
))
1428 tpm2_tpml_pcr_selection_cleanup(l
);
1430 assert(l
->count
< sizeof(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
, (TPML_PCR_SELECTION
*) 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
, (TPML_PCR_SELECTION
*) 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
, (TPML_PCR_SELECTION
*) 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
<= sizeof(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
) {
1528 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1529 log_debug("PCR index %u invalid.", pcr_value
->index
);
1533 /* If it contains a value, the value size must match the hash size. */
1534 if (pcr_value
->value
.size
> 0) {
1535 r
= tpm2_hash_alg_to_size(pcr_value
->hash
);
1539 if ((int) pcr_value
->value
.size
!= r
) {
1540 log_debug("PCR hash 0x%" PRIx16
" expected size %d does not match actual size %" PRIu16
".",
1541 pcr_value
->hash
, r
, pcr_value
->value
.size
);
1549 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1551 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1552 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1554 bool TPM2_PCR_VALUES_VALID(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1555 assert(pcr_values
|| n_pcr_values
== 0);
1557 for (size_t i
= 0; i
< n_pcr_values
; i
++) {
1558 const Tpm2PCRValue
*v
= &pcr_values
[i
];
1560 if (!TPM2_PCR_VALUE_VALID(v
))
1566 const Tpm2PCRValue
*l
= &pcr_values
[i
- 1];
1568 /* Hashes must be sorted in ascending order */
1569 if (v
->hash
< l
->hash
) {
1570 log_debug("PCR values not in ascending order, hash %" PRIu16
" is after %" PRIu16
".",
1575 if (v
->hash
== l
->hash
) {
1576 /* Indexes (for the same hash) must be sorted in ascending order */
1577 if (v
->index
< l
->index
) {
1578 log_debug("PCR values not in ascending order, hash %" PRIu16
" index %u is after %u.",
1579 v
->hash
, v
->index
, l
->index
);
1583 /* Indexes (for the same hash) must not be duplicates */
1584 if (v
->index
== l
->index
) {
1585 log_debug("PCR values contain duplicates for hash %" PRIu16
" index %u.",
1595 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1599 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
1602 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1603 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1604 void tpm2_sort_pcr_values(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1605 typesafe_qsort(pcr_values
, n_pcr_values
, cmp_pcr_values
);
1608 int tpm2_pcr_values_from_mask(uint32_t mask
, TPMI_ALG_HASH hash
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1609 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1610 size_t n_pcr_values
= 0;
1612 assert(ret_pcr_values
);
1613 assert(ret_n_pcr_values
);
1615 FOREACH_PCR_IN_MASK(index
, mask
)
1616 if (!GREEDY_REALLOC_APPEND(
1619 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1621 return log_oom_debug();
1623 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1624 *ret_n_pcr_values
= n_pcr_values
;
1629 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1632 assert(pcr_values
|| n_pcr_values
== 0);
1635 if (!TPM2_PCR_VALUES_VALID(pcr_values
, n_pcr_values
))
1636 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1638 for (size_t i
= 0; i
< n_pcr_values
; i
++)
1639 if (pcr_values
[i
].hash
== hash
)
1640 SET_BIT(mask
, pcr_values
[i
].index
);
1647 int tpm2_tpml_pcr_selection_from_pcr_values(
1648 const Tpm2PCRValue
*pcr_values
,
1649 size_t n_pcr_values
,
1650 TPML_PCR_SELECTION
*ret_selection
,
1651 TPM2B_DIGEST
**ret_values
,
1652 size_t *ret_n_values
) {
1654 TPML_PCR_SELECTION selection
= {};
1655 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1656 size_t n_values
= 0;
1658 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
), "PCR values are not valid.");
1663 for (size_t i
= 0; i
< n_pcr_values
; i
++) {
1664 unsigned index
= pcr_values
[i
].index
;
1665 TPMI_ALG_HASH hash
= pcr_values
[i
].hash
;
1666 const TPM2B_DIGEST
*digest
= &pcr_values
[i
].value
;
1668 tpm2_tpml_pcr_selection_add_mask(&selection
, hash
, INDEX_TO_MASK(uint32_t, index
));
1670 if (!GREEDY_REALLOC_APPEND(values
, n_values
, digest
, 1))
1671 return log_oom_debug();
1675 *ret_selection
= selection
;
1677 *ret_values
= TAKE_PTR(values
);
1679 *ret_n_values
= n_values
;
1684 /* Count the number of different hash algorithms for all the entries. */
1685 int tpm2_pcr_values_hash_count(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, size_t *ret_count
) {
1686 TPML_PCR_SELECTION selection
;
1692 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1696 /* ret_values= */ NULL
,
1697 /* ret_n_values= */ NULL
);
1701 *ret_count
= selection
.count
;
1706 /* Parse a string argument into a Tpm2PCRValue object.
1708 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1709 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1710 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1711 int tpm2_pcr_value_from_string(const char *arg
, Tpm2PCRValue
*ret_pcr_value
) {
1712 Tpm2PCRValue pcr_value
= {};
1713 const char *p
= arg
;
1717 assert(ret_pcr_value
);
1719 _cleanup_free_
char *index
= NULL
;
1720 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1722 return log_error_errno(r
, "Could not parse pcr value '%s': %m", p
);
1724 r
= pcr_index_from_string(index
);
1726 return log_error_errno(r
, "Invalid pcr index '%s': %m", index
);
1727 pcr_value
.index
= (unsigned) r
;
1730 _cleanup_free_
char *hash
= NULL
;
1731 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1733 return log_error_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1735 r
= tpm2_hash_alg_from_string(hash
);
1737 return log_error_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1738 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1742 /* Remove leading 0x if present */
1743 p
= startswith_no_case(p
, "0x") ?: p
;
1745 _cleanup_free_
void *buf
= NULL
;
1746 size_t buf_size
= 0;
1747 r
= unhexmem(p
, strlen(p
), &buf
, &buf_size
);
1749 return log_error_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1751 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1753 return log_error_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1755 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1758 *ret_pcr_value
= pcr_value
;
1763 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1764 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1765 * string. This does not check for validity. */
1766 char *tpm2_pcr_value_to_string(const Tpm2PCRValue
*pcr_value
) {
1767 _cleanup_free_
char *index
= NULL
, *value
= NULL
;
1770 r
= asprintf(&index
, "%u", pcr_value
->index
);
1774 const char *hash
= tpm2_hash_alg_to_string(pcr_value
->hash
);
1776 if (hash
&& pcr_value
->value
.size
> 0) {
1777 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1782 return strjoin(index
, hash
? ":" : "", hash
?: "", value
? "=" : "", value
?: "");
1785 /* Parse a string argument into an array of Tpm2PCRValue objects.
1787 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1788 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1789 int tpm2_pcr_values_from_string(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
1790 const char *p
= arg
;
1794 assert(ret_pcr_values
);
1795 assert(ret_n_pcr_values
);
1797 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1798 size_t n_pcr_values
= 0;
1801 _cleanup_free_
char *pcr_arg
= NULL
;
1802 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1804 return log_error_errno(r
, "Could not parse pcr values '%s': %m", p
);
1808 Tpm2PCRValue pcr_value
;
1809 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1813 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1817 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1818 *ret_n_pcr_values
= n_pcr_values
;
1823 /* Return a string representing the array of PCR values. The format is as described in
1824 * tpm2_pcr_values_from_string(). This does not check for validity. */
1825 char *tpm2_pcr_values_to_string(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1826 _cleanup_free_
char *s
= NULL
;
1828 for (size_t i
= 0; i
< n_pcr_values
; i
++) {
1829 _cleanup_free_
char *pcrstr
= tpm2_pcr_value_to_string(&pcr_values
[i
]);
1830 if (!pcrstr
|| !strextend_with_separator(&s
, "+", pcrstr
))
1834 return s
? TAKE_PTR(s
) : strdup("");
1837 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
1838 if (!DEBUG_LOGGING
|| !l
)
1841 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
1842 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
1845 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
1846 if (!DEBUG_LOGGING
|| !pcr_value
)
1849 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
1850 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
1853 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
1854 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
1857 _cleanup_free_
char *h
= hexmem(buffer
, size
);
1858 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
1861 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
1863 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
1866 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
1868 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
1871 static int tpm2_get_policy_digest(
1873 const Tpm2Handle
*session
,
1874 TPM2B_DIGEST
**ret_policy_digest
) {
1878 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
1884 log_debug("Acquiring policy digest.");
1886 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
1887 rc
= sym_Esys_PolicyGetDigest(
1889 session
->esys_handle
,
1894 if (rc
!= TSS2_RC_SUCCESS
)
1895 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1896 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc
));
1898 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
1900 if (ret_policy_digest
)
1901 *ret_policy_digest
= TAKE_PTR(policy_digest
);
1906 int tpm2_create_primary(
1908 const Tpm2Handle
*session
,
1909 const TPM2B_PUBLIC
*template,
1910 const TPM2B_SENSITIVE_CREATE
*sensitive
,
1911 TPM2B_PUBLIC
**ret_public
,
1912 Tpm2Handle
**ret_handle
) {
1921 log_debug("Creating primary key on TPM.");
1923 ts
= now(CLOCK_MONOTONIC
);
1925 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
1926 r
= tpm2_handle_new(c
, &handle
);
1930 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
1931 rc
= sym_Esys_CreatePrimary(
1934 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
1937 sensitive
? sensitive
: &(TPM2B_SENSITIVE_CREATE
) {},
1939 /* outsideInfo= */ NULL
,
1940 &(TPML_PCR_SELECTION
) {},
1941 &handle
->esys_handle
,
1943 /* creationData= */ NULL
,
1944 /* creationHash= */ NULL
,
1945 /* creationTicket= */ NULL
);
1946 if (rc
!= TSS2_RC_SUCCESS
)
1947 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1948 "Failed to generate primary key in TPM: %s",
1949 sym_Tss2_RC_Decode(rc
));
1951 log_debug("Successfully created primary key on TPM in %s.",
1952 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
1955 *ret_public
= TAKE_PTR(public);
1957 *ret_handle
= TAKE_PTR(handle
);
1962 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
1963 * instead use tpm2_create_primary(). */
1964 int tpm2_create(Tpm2Context
*c
,
1965 const Tpm2Handle
*parent
,
1966 const Tpm2Handle
*session
,
1967 const TPMT_PUBLIC
*template,
1968 const TPMS_SENSITIVE_CREATE
*sensitive
,
1969 TPM2B_PUBLIC
**ret_public
,
1970 TPM2B_PRIVATE
**ret_private
) {
1979 log_debug("Creating object on TPM.");
1981 ts
= now(CLOCK_MONOTONIC
);
1983 TPM2B_PUBLIC tpm2b_public
= {
1984 .size
= sizeof(*template) - sizeof(template->unique
),
1985 .publicArea
= *template,
1988 /* Zero the unique area. */
1989 zero(tpm2b_public
.publicArea
.unique
);
1991 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
1993 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
1994 .size
= sizeof(*sensitive
),
1995 .sensitive
= *sensitive
,
1998 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2000 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2001 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2002 rc
= sym_Esys_Create(
2004 parent
->esys_handle
,
2005 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2010 /* outsideInfo= */ NULL
,
2011 &(TPML_PCR_SELECTION
) {},
2014 /* creationData= */ NULL
,
2015 /* creationHash= */ NULL
,
2016 /* creationTicket= */ NULL
);
2017 if (rc
!= TSS2_RC_SUCCESS
)
2018 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2019 "Failed to generate object in TPM: %s",
2020 sym_Tss2_RC_Decode(rc
));
2022 log_debug("Successfully created object on TPM in %s.",
2023 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2026 *ret_public
= TAKE_PTR(public);
2028 *ret_private
= TAKE_PTR(private);
2033 static int tpm2_load(
2035 const Tpm2Handle
*parent
,
2036 const Tpm2Handle
*session
,
2037 const TPM2B_PUBLIC
*public,
2038 const TPM2B_PRIVATE
*private,
2039 Tpm2Handle
**ret_handle
) {
2049 log_debug("Loading object into TPM.");
2051 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2052 r
= tpm2_handle_new(c
, &handle
);
2058 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2059 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2064 &handle
->esys_handle
);
2065 if (rc
== TPM2_RC_LOCKOUT
)
2066 return log_error_errno(SYNTHETIC_ERRNO(ENOLCK
),
2067 "TPM2 device is in dictionary attack lockout mode.");
2068 if (rc
!= TSS2_RC_SUCCESS
)
2069 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2070 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2072 *ret_handle
= TAKE_PTR(handle
);
2077 static int tpm2_load_external(
2079 const Tpm2Handle
*session
,
2080 const TPM2B_PUBLIC
*public,
2081 const TPM2B_SENSITIVE
*private,
2082 Tpm2Handle
**ret_handle
) {
2090 log_debug("Loading external key into TPM.");
2092 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2093 r
= tpm2_handle_new(c
, &handle
);
2097 rc
= sym_Esys_LoadExternal(
2099 session
? session
->esys_handle
: ESYS_TR_NONE
,
2105 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2106 * hierarchy, older versions need TPM2_RH_* instead. */
2111 &handle
->esys_handle
);
2112 if (rc
!= TSS2_RC_SUCCESS
)
2113 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2114 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc
));
2116 *ret_handle
= TAKE_PTR(handle
);
2121 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2122 * use tpm2_create_loaded(). */
2123 static int _tpm2_create_loaded(
2125 const Tpm2Handle
*parent
,
2126 const Tpm2Handle
*session
,
2127 const TPMT_PUBLIC
*template,
2128 const TPMS_SENSITIVE_CREATE
*sensitive
,
2129 TPM2B_PUBLIC
**ret_public
,
2130 TPM2B_PRIVATE
**ret_private
,
2131 Tpm2Handle
**ret_handle
) {
2141 log_debug("Creating loaded object on TPM.");
2143 ts
= now(CLOCK_MONOTONIC
);
2145 /* Copy the input template and zero the unique area. */
2146 TPMT_PUBLIC template_copy
= *template;
2147 zero(template_copy
.unique
);
2149 TPM2B_TEMPLATE tpm2b_template
;
2151 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2153 tpm2b_template
.buffer
,
2154 sizeof(tpm2b_template
.buffer
),
2156 if (rc
!= TSS2_RC_SUCCESS
)
2157 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2158 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc
));
2159 assert(size
<= UINT16_MAX
);
2160 tpm2b_template
.size
= size
;
2162 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2164 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2165 .size
= sizeof(*sensitive
),
2166 .sensitive
= *sensitive
,
2169 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2171 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2172 r
= tpm2_handle_new(c
, &handle
);
2176 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2177 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2178 rc
= sym_Esys_CreateLoaded(
2180 parent
->esys_handle
,
2181 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2186 &handle
->esys_handle
,
2189 if (rc
!= TSS2_RC_SUCCESS
)
2190 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2191 "Failed to generate loaded object in TPM: %s",
2192 sym_Tss2_RC_Decode(rc
));
2194 log_debug("Successfully created loaded object on TPM in %s.",
2195 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2198 *ret_public
= TAKE_PTR(public);
2200 *ret_private
= TAKE_PTR(private);
2202 *ret_handle
= TAKE_PTR(handle
);
2207 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2208 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2209 * tpm2_create_primary(). */
2210 int tpm2_create_loaded(
2212 const Tpm2Handle
*parent
,
2213 const Tpm2Handle
*session
,
2214 const TPMT_PUBLIC
*template,
2215 const TPMS_SENSITIVE_CREATE
*sensitive
,
2216 TPM2B_PUBLIC
**ret_public
,
2217 TPM2B_PRIVATE
**ret_private
,
2218 Tpm2Handle
**ret_handle
) {
2222 if (tpm2_supports_command(c
, TPM2_CC_CreateLoaded
))
2223 return _tpm2_create_loaded(c
, parent
, session
, template, sensitive
, ret_public
, ret_private
, ret_handle
);
2225 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2226 * create and load manually. */
2227 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2228 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2229 r
= tpm2_create(c
, parent
, session
, template, sensitive
, &public, &private);
2233 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2234 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2239 *ret_public
= TAKE_PTR(public);
2241 *ret_private
= TAKE_PTR(private);
2243 *ret_handle
= TAKE_PTR(handle
);
2248 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2249 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2250 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2251 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2255 const TPML_PCR_SELECTION
*pcr_selection
,
2256 Tpm2PCRValue
**ret_pcr_values
,
2257 size_t *ret_n_pcr_values
) {
2259 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2260 size_t n_pcr_values
= 0;
2264 assert(pcr_selection
);
2265 assert(ret_pcr_values
);
2266 assert(ret_n_pcr_values
);
2268 TPML_PCR_SELECTION remaining
= *pcr_selection
;
2269 while (!tpm2_tpml_pcr_selection_is_empty(&remaining
)) {
2270 _cleanup_(Esys_Freep
) TPML_PCR_SELECTION
*current_read
= NULL
;
2271 _cleanup_(Esys_Freep
) TPML_DIGEST
*current_values
= NULL
;
2273 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2275 /* Unfortunately, PCR_Read will not return more than 8 values. */
2276 rc
= sym_Esys_PCR_Read(
2285 if (rc
!= TSS2_RC_SUCCESS
)
2286 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2287 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc
));
2289 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2291 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2292 log_warning("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2297 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2298 assert(i
< current_values
->count
);
2299 Tpm2PCRValue pcr_value
= {
2302 .value
= current_values
->digests
[i
++],
2305 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2307 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2310 assert(i
== current_values
->count
);
2312 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2315 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
2317 if (!TPM2_PCR_VALUES_VALID(pcr_values
, n_pcr_values
))
2318 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "PCR values read from TPM are not valid.");
2320 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2321 *ret_n_pcr_values
= n_pcr_values
;
2326 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2327 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2328 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2329 * appropriate entries, this returns an error. This does not check the array for validity. */
2330 int tpm2_pcr_read_missing_values(Tpm2Context
*c
, Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
2331 TPMI_ALG_HASH pcr_bank
= 0;
2335 assert(pcr_values
|| n_pcr_values
== 0);
2337 if (n_pcr_values
> 0) {
2339 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2341 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
2343 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2345 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2349 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2355 for (size_t i
= 0; i
< n_pcr_values
; i
++) {
2356 Tpm2PCRValue
*v
= &pcr_values
[i
];
2361 if (v
->value
.size
> 0)
2364 TPML_PCR_SELECTION selection
;
2365 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
2369 _cleanup_free_ Tpm2PCRValue
*read_values
= NULL
;
2370 size_t n_read_values
;
2371 r
= tpm2_pcr_read(c
, &selection
, &read_values
, &n_read_values
);
2375 if (n_read_values
== 0)
2376 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2377 "Could not read PCR hash 0x%" PRIu16
" index %u",
2380 assert(n_read_values
== 1);
2381 assert(read_values
[0].hash
== v
->hash
);
2382 assert(read_values
[0].index
== v
->index
);
2384 v
->value
= read_values
[0].value
;
2390 static int tpm2_pcr_mask_good(
2395 TPML_PCR_SELECTION selection
;
2400 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2401 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2402 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2404 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
2406 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2407 size_t n_pcr_values
;
2408 r
= tpm2_pcr_read(c
, &selection
, &pcr_values
, &n_pcr_values
);
2412 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2413 for (unsigned i
= 0; i
< n_pcr_values
; i
++)
2414 if (!memeqbyte(0x00, pcr_values
[i
].value
.buffer
, pcr_values
[i
].value
.size
) &&
2415 !memeqbyte(0xFF, pcr_values
[i
].value
.buffer
, pcr_values
[i
].value
.size
))
2421 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
2425 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2426 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2427 if (selection
->sizeofSelect
< TPM2_PCRS_MAX
/8) {
2428 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2429 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2433 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
2435 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2436 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2438 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2439 if (selection
->pcrSelect
[j
] != 0xFF) {
2445 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2446 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2451 int tpm2_get_best_pcr_bank(
2454 TPMI_ALG_HASH
*ret
) {
2456 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
2462 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2463 TPMI_ALG_HASH hash
= selection
->hash
;
2466 /* For now we are only interested in the SHA1 and SHA256 banks */
2467 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2470 r
= tpm2_bank_has24(selection
);
2476 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2480 if (hash
== TPM2_ALG_SHA256
) {
2481 supported_hash
= TPM2_ALG_SHA256
;
2483 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2484 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2488 assert(hash
== TPM2_ALG_SHA1
);
2490 if (supported_hash
== 0)
2491 supported_hash
= TPM2_ALG_SHA1
;
2493 if (good
&& hash_with_valid_pcr
== 0)
2494 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
2498 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2499 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2502 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2503 * not initialized. */
2505 if (hash_with_valid_pcr
== TPM2_ALG_SHA256
) {
2506 assert(supported_hash
== TPM2_ALG_SHA256
);
2507 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2508 *ret
= TPM2_ALG_SHA256
;
2509 } else if (hash_with_valid_pcr
== TPM2_ALG_SHA1
) {
2510 if (supported_hash
== TPM2_ALG_SHA256
)
2511 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.");
2513 assert(supported_hash
== TPM2_ALG_SHA1
);
2514 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.");
2517 *ret
= TPM2_ALG_SHA1
;
2518 } else if (supported_hash
== TPM2_ALG_SHA256
) {
2519 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!");
2520 *ret
= TPM2_ALG_SHA256
;
2521 } else if (supported_hash
== TPM2_ALG_SHA1
) {
2522 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!");
2523 *ret
= TPM2_ALG_SHA1
;
2525 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2526 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2531 int tpm2_get_good_pcr_banks(
2534 TPMI_ALG_HASH
**ret
) {
2536 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2537 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2543 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2544 TPMI_ALG_HASH hash
= selection
->hash
;
2546 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2547 r
= tpm2_bank_has24(selection
);
2553 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2554 r
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2558 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2559 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2562 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2565 good_banks
[n_good_banks
++] = hash
;
2567 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2570 fallback_banks
[n_fallback_banks
++] = hash
;
2574 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2575 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2576 if (n_good_banks
> 0) {
2577 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks
);
2578 *ret
= TAKE_PTR(good_banks
);
2579 return (int) n_good_banks
;
2581 if (n_fallback_banks
> 0) {
2582 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks
);
2583 *ret
= TAKE_PTR(fallback_banks
);
2584 return (int) n_fallback_banks
;
2587 /* No suitable banks found. */
2592 int tpm2_get_good_pcr_banks_strv(
2598 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2599 _cleanup_strv_free_
char **l
= NULL
;
2605 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2609 for (int i
= 0; i
< n_algs
; i
++) {
2610 _cleanup_free_
char *n
= NULL
;
2611 const EVP_MD
*implementation
;
2614 salg
= tpm2_hash_alg_to_string(algs
[i
]);
2616 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
2618 implementation
= EVP_get_digestbyname(salg
);
2619 if (!implementation
)
2620 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2622 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2626 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2628 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2634 #else /* HAVE_OPENSSL */
2635 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2639 /* Hash data into the digest.
2641 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2642 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2643 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2644 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2646 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2647 * correct for 'alg'.
2649 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2650 int tpm2_digest_many(
2652 TPM2B_DIGEST
*digest
,
2653 const struct iovec data
[],
2657 struct sha256_ctx ctx
;
2660 assert(data
|| n_data
== 0);
2662 if (alg
!= TPM2_ALG_SHA256
)
2663 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2664 "Hash algorithm not supported: 0x%x", alg
);
2666 if (extend
&& digest
->size
!= SHA256_DIGEST_SIZE
)
2667 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2668 "Digest size 0x%x, require 0x%x",
2669 digest
->size
, (unsigned)SHA256_DIGEST_SIZE
);
2671 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2672 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
2676 sha256_init_ctx(&ctx
);
2679 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
2681 *digest
= (TPM2B_DIGEST
){ .size
= SHA256_DIGEST_SIZE
, };
2682 if (n_data
== 0) /* If not extending and no data, return zero hash */
2686 for (size_t i
= 0; i
< n_data
; i
++)
2687 sha256_process_bytes(data
[i
].iov_base
, data
[i
].iov_len
, &ctx
);
2689 sha256_finish_ctx(&ctx
, digest
->buffer
);
2694 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2695 int tpm2_digest_many_digests(
2697 TPM2B_DIGEST
*digest
,
2698 const TPM2B_DIGEST data
[],
2702 _cleanup_free_
struct iovec
*iovecs
= NULL
;
2704 assert(data
|| n_data
== 0);
2706 iovecs
= new(struct iovec
, n_data
);
2710 for (size_t i
= 0; i
< n_data
; i
++)
2711 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
2713 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
2716 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
2717 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
2718 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
2719 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
2720 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2722 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2723 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2724 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2725 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2727 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2728 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2729 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2731 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2732 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2733 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2734 * which we will trim the 0(s) from before sending to the TPM.
2736 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
2737 bool trimmed
= false;
2741 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
2747 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2750 static int tpm2_get_pin_auth(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
2751 TPM2B_AUTH auth
= {};
2757 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
2761 tpm2_trim_auth_value(&auth
);
2763 *ret_auth
= TAKE_STRUCT(auth
);
2768 static int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
2769 TPM2B_AUTH auth
= {};
2779 CLEANUP_ERASE(auth
);
2781 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &auth
);
2785 rc
= sym_Esys_TR_SetAuth(c
->esys_context
, handle
->esys_handle
, &auth
);
2786 if (rc
!= TSS2_RC_SUCCESS
)
2787 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2788 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc
));
2793 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
2794 TPMA_SESSION flags
= 0;
2800 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
2801 if (rc
!= TSS2_RC_SUCCESS
)
2804 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
2807 static int tpm2_make_encryption_session(
2809 const Tpm2Handle
*primary
,
2810 const Tpm2Handle
*bind_key
,
2811 Tpm2Handle
**ret_session
) {
2813 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
2814 TPMA_SESSION_CONTINUESESSION
;
2819 assert(ret_session
);
2821 log_debug("Starting HMAC encryption session.");
2823 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2824 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2825 * recover the salt, which is then used for key derivation. */
2826 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2827 r
= tpm2_handle_new(c
, &session
);
2831 rc
= sym_Esys_StartAuthSession(
2833 primary
->esys_handle
,
2834 bind_key
->esys_handle
,
2840 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2842 &session
->esys_handle
);
2843 if (rc
!= TSS2_RC_SUCCESS
)
2844 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2845 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2847 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2848 * always used for sessions), this provides confidentiality, integrity and replay protection for
2849 * operations that use this session. */
2850 rc
= sym_Esys_TRSess_SetAttributes(c
->esys_context
, session
->esys_handle
, sessionAttributes
, 0xff);
2851 if (rc
!= TSS2_RC_SUCCESS
)
2852 return log_error_errno(
2853 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2854 "Failed to configure TPM session: %s",
2855 sym_Tss2_RC_Decode(rc
));
2857 *ret_session
= TAKE_PTR(session
);
2862 static int tpm2_make_policy_session(
2864 const Tpm2Handle
*primary
,
2865 const Tpm2Handle
*encryption_session
,
2867 Tpm2Handle
**ret_session
) {
2869 TPM2_SE session_type
= trial
? TPM2_SE_TRIAL
: TPM2_SE_POLICY
;
2875 assert(encryption_session
);
2876 assert(ret_session
);
2878 if (!tpm2_is_encryption_session(c
, encryption_session
))
2879 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2880 "Missing encryption session");
2882 log_debug("Starting policy session.");
2884 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
2885 r
= tpm2_handle_new(c
, &session
);
2889 rc
= sym_Esys_StartAuthSession(
2891 primary
->esys_handle
,
2893 encryption_session
->esys_handle
,
2898 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
2900 &session
->esys_handle
);
2901 if (rc
!= TSS2_RC_SUCCESS
)
2902 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2903 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc
));
2905 *ret_session
= TAKE_PTR(session
);
2910 static int find_signature(
2912 const TPML_PCR_SELECTION
*pcr_selection
,
2917 void *ret_signature
,
2918 size_t *ret_signature_size
) {
2925 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
2926 * public key, and policy digest. */
2928 if (!json_variant_is_object(v
))
2929 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
2931 uint16_t pcr_bank
= pcr_selection
->pcrSelections
[0].hash
;
2932 uint32_t pcr_mask
= tpm2_tpml_pcr_selection_to_mask(pcr_selection
, pcr_bank
);
2934 k
= tpm2_hash_alg_to_string(pcr_bank
);
2936 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
2938 /* First, find field by bank */
2939 b
= json_variant_by_key(v
, k
);
2941 return log_error_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
2943 if (!json_variant_is_array(b
))
2944 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
2946 /* Now iterate through all signatures known for this bank */
2947 JSON_VARIANT_ARRAY_FOREACH(i
, b
) {
2948 _cleanup_free_
void *fpj_data
= NULL
, *polj_data
= NULL
;
2949 JsonVariant
*maskj
, *fpj
, *sigj
, *polj
;
2950 size_t fpj_size
, polj_size
;
2951 uint32_t parsed_mask
;
2953 if (!json_variant_is_object(i
))
2954 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
2956 /* Check if the PCR mask matches our expectations */
2957 maskj
= json_variant_by_key(i
, "pcrs");
2961 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
2963 return log_error_errno(r
, "Failed to parse JSON PCR mask");
2965 if (parsed_mask
!= pcr_mask
)
2966 continue; /* Not for this PCR mask */
2968 /* Then check if this is for the public key we operate with */
2969 fpj
= json_variant_by_key(i
, "pkfp");
2973 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
2975 return log_error_errno(r
, "Failed to decode fingerprint in JSON data: %m");
2977 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
2978 continue; /* Not for this public key */
2980 /* Finally, check if this is for the PCR policy we expect this to be */
2981 polj
= json_variant_by_key(i
, "pol");
2985 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
2987 return log_error_errno(r
, "Failed to decode policy hash JSON data: %m");
2989 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
2992 /* This entry matches all our expectations, now return the signature included in it */
2993 sigj
= json_variant_by_key(i
, "sig");
2997 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
3000 return log_error_errno(SYNTHETIC_ERRNO(ENXIO
), "Couldn't find signature for this PCR bank, PCR index and public key.");
3001 #else /* HAVE_OPENSSL */
3002 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3006 /* Calculates the "name" of a public key.
3008 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3009 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3010 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3011 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3012 * that would also change the key name.
3014 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3015 * nameAlg is not TPM2_ALG_SHA256. */
3016 int tpm2_calculate_name(const TPMT_PUBLIC
*public, TPM2B_NAME
*ret_name
) {
3025 return log_error_errno(r
, "TPM2 support not installed: %m");
3027 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3028 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3029 "Unsupported nameAlg: 0x%x",
3032 _cleanup_free_
uint8_t *buf
= NULL
;
3035 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3039 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf
, sizeof(TPMT_PUBLIC
), &size
);
3040 if (rc
!= TSS2_RC_SUCCESS
)
3041 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3042 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3044 TPM2B_DIGEST digest
= {};
3045 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3050 .hashAlg
= TPM2_ALG_SHA256
,
3052 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3053 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
3057 rc
= sym_Tss2_MU_TPMT_HA_Marshal(&ha
, name
.name
, sizeof(name
.name
), &size
);
3058 if (rc
!= TSS2_RC_SUCCESS
)
3059 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3060 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc
));
3063 tpm2_log_debug_name(&name
, "Calculated name");
3070 /* Get the "name" of a key from the TPM.
3072 * The "name" of a key is explained above in tpm2_calculate_name().
3074 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3075 * public/private keypair. */
3076 static int tpm2_get_name(
3078 const Tpm2Handle
*handle
,
3079 TPM2B_NAME
**ret_name
) {
3081 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
3088 rc
= sym_Esys_TR_GetName(c
->esys_context
, handle
->esys_handle
, &name
);
3089 if (rc
!= TSS2_RC_SUCCESS
)
3090 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3091 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc
));
3093 tpm2_log_debug_name(name
, "Object name");
3095 *ret_name
= TAKE_PTR(name
);
3100 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3101 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST
*digest
) {
3102 TPM2_CC command
= TPM2_CC_PolicyAuthValue
;
3107 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3111 return log_error_errno(r
, "TPM2 support not installed: %m");
3113 uint8_t buf
[sizeof(command
)];
3116 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3117 if (rc
!= TSS2_RC_SUCCESS
)
3118 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3119 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc
));
3121 if (offset
!= sizeof(command
))
3122 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3123 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3125 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3129 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3134 static int tpm2_policy_auth_value(
3136 const Tpm2Handle
*session
,
3137 TPM2B_DIGEST
**ret_policy_digest
) {
3144 log_debug("Adding authValue policy.");
3146 rc
= sym_Esys_PolicyAuthValue(
3148 session
->esys_handle
,
3152 if (rc
!= TSS2_RC_SUCCESS
)
3153 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3154 "Failed to add authValue policy to TPM: %s",
3155 sym_Tss2_RC_Decode(rc
));
3157 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3160 /* Extend 'digest' with the PolicyPCR calculated hash. */
3161 int tpm2_calculate_policy_pcr(
3162 const Tpm2PCRValue
*pcr_values
,
3163 size_t n_pcr_values
,
3164 TPM2B_DIGEST
*digest
) {
3166 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3170 assert(pcr_values
|| n_pcr_values
== 0);
3172 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3176 return log_error_errno(r
, "TPM2 support not installed: %m");
3178 TPML_PCR_SELECTION pcr_selection
;
3179 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3181 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3183 return log_error_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3185 TPM2B_DIGEST hash
= {};
3186 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3190 _cleanup_free_
uint8_t *buf
= NULL
;
3191 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3193 buf
= malloc(maxsize
);
3197 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, maxsize
, &size
);
3198 if (rc
!= TSS2_RC_SUCCESS
)
3199 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3200 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc
));
3202 rc
= sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection
, buf
, maxsize
, &size
);
3203 if (rc
!= TSS2_RC_SUCCESS
)
3204 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3205 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc
));
3207 struct iovec data
[] = {
3208 IOVEC_MAKE(buf
, size
),
3209 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3211 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3215 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3220 static int tpm2_policy_pcr(
3222 const Tpm2Handle
*session
,
3223 const TPML_PCR_SELECTION
*pcr_selection
,
3224 TPM2B_DIGEST
**ret_policy_digest
) {
3230 assert(pcr_selection
);
3232 log_debug("Adding PCR hash policy.");
3234 rc
= sym_Esys_PolicyPCR(
3236 session
->esys_handle
,
3242 if (rc
!= TSS2_RC_SUCCESS
)
3243 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3244 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc
));
3246 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3249 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3250 int tpm2_calculate_policy_authorize(
3251 const TPM2B_PUBLIC
*public,
3252 const TPM2B_DIGEST
*policy_ref
,
3253 TPM2B_DIGEST
*digest
) {
3255 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3261 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3265 return log_error_errno(r
, "TPM2 support not installed: %m");
3267 uint8_t buf
[sizeof(command
)];
3270 rc
= sym_Tss2_MU_TPM2_CC_Marshal(command
, buf
, sizeof(buf
), &offset
);
3271 if (rc
!= TSS2_RC_SUCCESS
)
3272 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3273 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc
));
3275 if (offset
!= sizeof(command
))
3276 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3277 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
3279 TPM2B_NAME name
= {};
3280 r
= tpm2_calculate_name(&public->publicArea
, &name
);
3284 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3285 zero(digest
->buffer
);
3287 struct iovec data
[] = {
3288 IOVEC_MAKE(buf
, offset
),
3289 IOVEC_MAKE(name
.name
, name
.size
),
3291 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3295 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3297 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
3299 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
3303 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
3308 static int tpm2_policy_authorize(
3310 const Tpm2Handle
*session
,
3311 TPML_PCR_SELECTION
*pcr_selection
,
3312 const TPM2B_PUBLIC
*public,
3315 JsonVariant
*signature_json
,
3316 TPM2B_DIGEST
**ret_policy_digest
) {
3323 assert(pcr_selection
);
3325 assert(fp
&& fp_size
> 0);
3327 log_debug("Adding PCR signature policy.");
3329 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
3330 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
3334 /* Acquire the "name" of what we just loaded */
3335 _cleanup_(Esys_Freep
) TPM2B_NAME
*pubkey_name
= NULL
;
3336 r
= tpm2_get_name(c
, pubkey_handle
, &pubkey_name
);
3340 /* If we have a signature, proceed with verifying the PCR digest */
3341 const TPMT_TK_VERIFIED
*check_ticket
;
3342 _cleanup_(Esys_Freep
) TPMT_TK_VERIFIED
*check_ticket_buffer
= NULL
;
3343 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*approved_policy
= NULL
;
3344 if (signature_json
) {
3345 r
= tpm2_policy_pcr(
3353 _cleanup_free_
void *signature_raw
= NULL
;
3354 size_t signature_size
;
3360 approved_policy
->buffer
,
3361 approved_policy
->size
,
3367 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3368 * hence we need to do the SHA256 part ourselves, first */
3369 TPM2B_DIGEST signature_hash
= *approved_policy
;
3370 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, &signature_hash
);
3374 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
3376 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
3378 TPMT_SIGNATURE policy_signature
= {
3379 .sigAlg
= TPM2_ALG_RSASSA
,
3380 .signature
.rsassa
= {
3381 .hash
= TPM2_ALG_SHA256
,
3382 .sig
= TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw
, signature_size
),
3386 rc
= sym_Esys_VerifySignature(
3388 pubkey_handle
->esys_handle
,
3394 &check_ticket_buffer
);
3395 if (rc
!= TSS2_RC_SUCCESS
)
3396 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3397 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc
));
3399 check_ticket
= check_ticket_buffer
;
3401 /* When enrolling, we pass a NULL ticket */
3402 static const TPMT_TK_VERIFIED check_ticket_null
= {
3403 .tag
= TPM2_ST_VERIFIED
,
3404 .hierarchy
= TPM2_RH_OWNER
,
3407 check_ticket
= &check_ticket_null
;
3410 rc
= sym_Esys_PolicyAuthorize(
3412 session
->esys_handle
,
3417 /* policyRef= */ &(const TPM2B_NONCE
) {},
3420 if (rc
!= TSS2_RC_SUCCESS
)
3421 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3422 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc
));
3424 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3427 /* Extend 'digest' with the calculated policy hash. */
3428 static int tpm2_calculate_sealing_policy(
3429 const Tpm2PCRValue
*pcr_values
,
3430 size_t n_pcr_values
,
3431 const TPM2B_PUBLIC
*public,
3433 TPM2B_DIGEST
*digest
) {
3437 assert(pcr_values
|| n_pcr_values
== 0);
3441 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
3446 if (n_pcr_values
> 0) {
3447 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
3453 r
= tpm2_calculate_policy_auth_value(digest
);
3461 static int tpm2_build_sealing_policy(
3463 const Tpm2Handle
*session
,
3464 uint32_t hash_pcr_mask
,
3466 const TPM2B_PUBLIC
*public,
3469 uint32_t pubkey_pcr_mask
,
3470 JsonVariant
*signature_json
,
3472 TPM2B_DIGEST
**ret_policy_digest
) {
3478 assert(pubkey_pcr_mask
== 0 || public);
3480 log_debug("Building sealing policy.");
3482 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
3483 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
3487 log_warning("Selected TPM2 PCRs are not initialized on this system.");
3490 if (pubkey_pcr_mask
!= 0) {
3491 TPML_PCR_SELECTION pcr_selection
;
3492 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3493 r
= tpm2_policy_authorize(c
, session
, &pcr_selection
, public, fp
, fp_size
, signature_json
, NULL
);
3498 if (hash_pcr_mask
!= 0) {
3499 TPML_PCR_SELECTION pcr_selection
;
3500 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, (TPMI_ALG_HASH
)pcr_bank
, &pcr_selection
);
3501 r
= tpm2_policy_pcr(c
, session
, &pcr_selection
, NULL
);
3507 r
= tpm2_policy_auth_value(c
, session
, NULL
);
3512 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3520 static int tpm2_ecc_curve_from_openssl_curve_id(int curve_id
, TPM2_ECC_CURVE
*ret
) {
3524 case NID_X9_62_prime192v1
: *ret
= TPM2_ECC_NIST_P192
; return 0;
3525 case NID_secp224r1
: *ret
= TPM2_ECC_NIST_P192
; return 0;
3526 case NID_X9_62_prime256v1
: *ret
= TPM2_ECC_NIST_P256
; return 0;
3527 case NID_secp384r1
: *ret
= TPM2_ECC_NIST_P384
; return 0;
3528 case NID_secp521r1
: *ret
= TPM2_ECC_NIST_P521
; return 0;
3529 case NID_sm2
: *ret
= TPM2_ECC_SM2_P256
; return 0;
3532 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3533 "Openssl ECC curve id %d not supported.", curve_id
);
3536 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE curve
, int *ret
) {
3540 case TPM2_ECC_NIST_P192
: *ret
= NID_X9_62_prime192v1
; return 0;
3541 case TPM2_ECC_NIST_P224
: *ret
= NID_secp224r1
; return 0;
3542 case TPM2_ECC_NIST_P256
: *ret
= NID_X9_62_prime256v1
; return 0;
3543 case TPM2_ECC_NIST_P384
: *ret
= NID_secp384r1
; return 0;
3544 case TPM2_ECC_NIST_P521
: *ret
= NID_secp521r1
; return 0;
3545 case TPM2_ECC_SM2_P256
: *ret
= NID_sm2
; return 0;
3548 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3549 "TPM2 ECC curve %u not supported.", curve
);
3552 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
3554 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
3560 const TPMT_PUBLIC
*p
= &public->publicArea
;
3561 if (p
->type
== TPM2_ALG_ECC
) {
3563 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
3567 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
3568 return ecc_pkey_from_curve_x_y(
3577 if (p
->type
== TPM2_ALG_RSA
) {
3578 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
3579 * zero indicates that the exponent is the default of 2^16 + 1". */
3580 uint32_t exponent
= htobe32(p
->parameters
.rsaDetail
.exponent
?: TPM2_RSA_DEFAULT_EXPONENT
);
3581 return rsa_pkey_from_n_e(
3582 p
->unique
.rsa
.buffer
,
3589 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3590 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
3593 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY
*pkey
, TPM2B_PUBLIC
*ret
) {
3599 TPMT_PUBLIC
public = {
3600 .nameAlg
= TPM2_ALG_SHA256
,
3601 .objectAttributes
= TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
,
3602 .parameters
.asymDetail
= {
3603 .symmetric
.algorithm
= TPM2_ALG_NULL
,
3604 .scheme
.scheme
= TPM2_ALG_NULL
,
3608 #if OPENSSL_VERSION_MAJOR >= 3
3609 key_id
= EVP_PKEY_get_id(pkey
);
3611 key_id
= EVP_PKEY_id(pkey
);
3614 if (key_id
== EVP_PKEY_EC
) {
3615 public.type
= TPM2_ALG_ECC
;
3618 _cleanup_free_
void *x
= NULL
, *y
= NULL
;
3619 size_t x_size
, y_size
;
3620 r
= ecc_pkey_to_curve_x_y(pkey
, &curve_id
, &x
, &x_size
, &y
, &y_size
);
3622 return log_error_errno(r
, "Could not get ECC key curve/x/y: %m");
3624 TPM2_ECC_CURVE curve
;
3625 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
3629 public.parameters
.eccDetail
.curveID
= curve
;
3631 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
3633 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
3635 return log_error_errno(r
, "ECC key x size %zu too large.", x_size
);
3637 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
3639 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
3641 return log_error_errno(r
, "ECC key y size %zu too large.", y_size
);
3643 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
3644 } else if (key_id
== EVP_PKEY_RSA
) {
3645 public.type
= TPM2_ALG_RSA
;
3647 _cleanup_free_
void *n
= NULL
, *e
= NULL
;
3648 size_t n_size
, e_size
;
3649 r
= rsa_pkey_to_n_e(pkey
, &n
, &n_size
, &e
, &e_size
);
3651 return log_error_errno(r
, "Could not get RSA key n/e: %m");
3653 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
3655 return log_error_errno(r
, "RSA key n size %zu too large.", n_size
);
3657 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
3658 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
3660 if (sizeof(uint32_t) < e_size
)
3661 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3662 "RSA key e size %zu too large.", e_size
);
3664 uint32_t exponent
= 0;
3665 memcpy((void*) &exponent
, e
, e_size
);
3666 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
3667 if (exponent
== TPM2_RSA_DEFAULT_EXPONENT
)
3669 public.parameters
.rsaDetail
.exponent
= exponent
;
3671 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3672 "EVP_PKEY type %d not supported.", key_id
);
3674 *ret
= (TPM2B_PUBLIC
) {
3675 .size
= sizeof(public),
3676 .publicArea
= public,
3683 int tpm2_tpm2b_public_to_fingerprint(
3684 const TPM2B_PUBLIC
*public,
3685 void **ret_fingerprint
,
3686 size_t *ret_fingerprint_size
) {
3692 assert(ret_fingerprint
);
3693 assert(ret_fingerprint_size
);
3695 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3696 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
3700 /* Hardcode fingerprint to SHA256 */
3701 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
3703 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3707 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
3714 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
3715 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
3719 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
3721 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
3725 int tpm2_seal(const char *device
,
3726 uint32_t hash_pcr_mask
,
3728 const size_t pubkey_size
,
3729 uint32_t pubkey_pcr_mask
,
3732 size_t *ret_secret_size
,
3734 size_t *ret_blob_size
,
3735 void **ret_pcr_hash
,
3736 size_t *ret_pcr_hash_size
,
3737 uint16_t *ret_pcr_bank
,
3738 uint16_t *ret_primary_alg
,
3740 size_t *ret_srk_buf_size
) {
3745 assert(pubkey
|| pubkey_size
== 0);
3748 assert(ret_secret_size
);
3750 assert(ret_blob_size
);
3751 assert(ret_pcr_hash
);
3752 assert(ret_pcr_hash_size
);
3753 assert(ret_pcr_bank
);
3755 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
3756 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
3758 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3759 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
3760 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3761 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3762 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3763 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3764 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3765 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3766 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3767 * LUKS2 JSON header.
3769 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3770 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3771 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3772 * binding the unlocking to the TPM2 chip. */
3774 usec_t start
= now(CLOCK_MONOTONIC
);
3776 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*c
= NULL
;
3777 r
= tpm2_context_new(device
, &c
);
3781 TPMI_ALG_HASH pcr_bank
= 0;
3782 if (hash_pcr_mask
| pubkey_pcr_mask
) {
3783 /* Some TPM2 devices only can do SHA1. Prefer SHA256 but allow SHA1. */
3784 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
3789 _cleanup_free_ Tpm2PCRValue
*hash_pcr_values
= NULL
;
3790 size_t n_hash_pcr_values
;
3791 if (hash_pcr_mask
) {
3792 /* For now, we just read the current values from the system; we need to be able to specify
3793 * expected values, eventually. */
3794 TPML_PCR_SELECTION hash_pcr_selection
;
3795 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask
, pcr_bank
, &hash_pcr_selection
);
3797 r
= tpm2_pcr_read(c
, &hash_pcr_selection
, &hash_pcr_values
, &n_hash_pcr_values
);
3802 TPM2B_PUBLIC pubkey_tpm2b
;
3804 r
= tpm2_tpm2b_public_from_pem(pubkey
, pubkey_size
, &pubkey_tpm2b
);
3806 return log_error_errno(r
, "Could not create TPMT_PUBLIC: %m");
3809 TPM2B_DIGEST policy_digest
;
3810 r
= tpm2_digest_init(TPM2_ALG_SHA256
, &policy_digest
);
3814 r
= tpm2_calculate_sealing_policy(
3817 pubkey
? &pubkey_tpm2b
: NULL
,
3823 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3824 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3825 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
3826 TPMT_PUBLIC hmac_template
= {
3827 .type
= TPM2_ALG_KEYEDHASH
,
3828 .nameAlg
= TPM2_ALG_SHA256
,
3829 .objectAttributes
= TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT
,
3830 .parameters
.keyedHashDetail
.scheme
.scheme
= TPM2_ALG_NULL
,
3831 .unique
.keyedHash
.size
= SHA256_DIGEST_SIZE
,
3832 .authPolicy
= policy_digest
,
3835 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
3836 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
3839 CLEANUP_ERASE(hmac_sensitive
);
3842 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
3847 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
3849 (void) tpm2_credit_random(c
);
3851 log_debug("Generating secret key data.");
3853 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
3855 return log_error_errno(r
, "Failed to generate secret key: %m");
3857 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
3858 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
3860 r
= tpm2_get_or_create_srk(c
, NULL
, &primary_public
, NULL
, NULL
, &primary_handle
);
3864 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
3865 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
3866 r
= tpm2_get_legacy_template(TPM2_ALG_ECC
, &template.publicArea
);
3868 return log_error_errno(r
, "Could not get legacy ECC template: %m");
3870 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
3871 r
= tpm2_get_legacy_template(TPM2_ALG_RSA
, &template.publicArea
);
3873 return log_error_errno(r
, "Could not get legacy RSA template: %m");
3875 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
))
3876 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3877 "TPM does not support either ECC or RSA legacy template.");
3880 r
= tpm2_create_primary(
3882 /* session= */ NULL
,
3884 /* sensitive= */ NULL
,
3891 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
3892 r
= tpm2_make_encryption_session(c
, primary_handle
, &TPM2_HANDLE_NONE
, &encryption_session
);
3896 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
3897 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
3898 r
= tpm2_create(c
, primary_handle
, encryption_session
, &hmac_template
, &hmac_sensitive
, &public, &private);
3902 _cleanup_(erase_and_freep
) void *secret
= NULL
;
3903 secret
= memdup(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
3907 log_debug("Marshalling private and public part of HMAC key.");
3909 _cleanup_free_
void *blob
= NULL
;
3910 size_t max_size
= sizeof(*private) + sizeof(*public), blob_size
= 0;
3912 blob
= malloc0(max_size
);
3916 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob
, max_size
, &blob_size
);
3917 if (rc
!= TSS2_RC_SUCCESS
)
3918 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3919 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc
));
3921 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob
, max_size
, &blob_size
);
3922 if (rc
!= TSS2_RC_SUCCESS
)
3923 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3924 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc
));
3926 _cleanup_free_
void *hash
= NULL
;
3927 hash
= memdup(policy_digest
.buffer
, policy_digest
.size
);
3931 /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
3932 * the raw TPM handle as well as the object name. The object name is used to verify that
3933 * the key we use later is the key we expect to establish the session with.
3935 _cleanup_(Esys_Freep
) uint8_t *srk_buf
= NULL
;
3936 size_t srk_buf_size
= 0;
3938 log_debug("Serializing SRK ESYS_TR reference");
3939 rc
= sym_Esys_TR_Serialize(c
->esys_context
, primary_handle
->esys_handle
, &srk_buf
, &srk_buf_size
);
3940 if (rc
!= TSS2_RC_SUCCESS
)
3941 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3942 "Failed to serialize primary key: %s", sym_Tss2_RC_Decode(rc
));
3946 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
3950 * make a copy since we don't want the caller to understand that
3951 * ESYS allocated the pointer. It would make tracking what deallocator
3952 * to use for srk_buf in which context a PITA.
3954 void *tmp
= memdup(srk_buf
, srk_buf_size
);
3958 *ret_srk_buf
= TAKE_PTR(tmp
);
3959 *ret_srk_buf_size
= srk_buf_size
;
3962 *ret_secret
= TAKE_PTR(secret
);
3963 *ret_secret_size
= hmac_sensitive
.data
.size
;
3964 *ret_blob
= TAKE_PTR(blob
);
3965 *ret_blob_size
= blob_size
;
3966 *ret_pcr_hash
= TAKE_PTR(hash
);
3967 *ret_pcr_hash_size
= policy_digest
.size
;
3968 *ret_pcr_bank
= pcr_bank
;
3969 *ret_primary_alg
= primary_public
->publicArea
.type
;
3974 #define RETRY_UNSEAL_MAX 30u
3976 int tpm2_unseal(const char *device
,
3977 uint32_t hash_pcr_mask
,
3981 uint32_t pubkey_pcr_mask
,
3982 JsonVariant
*signature
,
3984 uint16_t primary_alg
,
3987 const void *known_policy_hash
,
3988 size_t known_policy_hash_size
,
3989 const void *srk_buf
,
3990 size_t srk_buf_size
,
3992 size_t *ret_secret_size
) {
3998 assert(blob_size
> 0);
3999 assert(known_policy_hash_size
== 0 || known_policy_hash
);
4000 assert(pubkey_size
== 0 || pubkey
);
4002 assert(ret_secret_size
);
4004 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
4005 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
4009 return log_error_errno(r
, "TPM2 support is not installed.");
4011 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
4012 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
4013 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
4014 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
4015 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
4016 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
4017 * and use it to unlock the LUKS2 volume. */
4019 usec_t start
= now(CLOCK_MONOTONIC
);
4021 log_debug("Unmarshalling private part of HMAC key.");
4023 TPM2B_PRIVATE
private = {};
4025 rc
= sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob
, blob_size
, &offset
, &private);
4026 if (rc
!= TSS2_RC_SUCCESS
)
4027 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4028 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc
));
4030 log_debug("Unmarshalling public part of HMAC key.");
4032 TPM2B_PUBLIC
public = {};
4033 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob
, blob_size
, &offset
, &public);
4034 if (rc
!= TSS2_RC_SUCCESS
)
4035 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4036 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc
));
4038 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*c
= NULL
;
4039 r
= tpm2_context_new(device
, &c
);
4043 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
4044 * so we need to handle that legacy situation. */
4045 if (pcr_bank
== UINT16_MAX
) {
4046 r
= tpm2_get_best_pcr_bank(c
, hash_pcr_mask
|pubkey_pcr_mask
, &pcr_bank
);
4051 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
4053 r
= tpm2_handle_new(c
, &primary_handle
);
4057 primary_handle
->flush
= false;
4059 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
4060 rc
= sym_Esys_TR_Deserialize(
4064 &primary_handle
->esys_handle
);
4065 if (rc
!= TSS2_RC_SUCCESS
)
4066 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4067 "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc
));
4068 } else if (primary_alg
!= 0) {
4069 TPM2B_PUBLIC
template = { .size
= sizeof(TPMT_PUBLIC
), };
4070 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
4072 return log_error_errno(r
, "Could not get legacy template: %m");
4074 r
= tpm2_create_primary(
4076 /* session= */ NULL
,
4078 /* sensitive= */ NULL
,
4079 /* ret_public= */ NULL
,
4084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
4085 "No SRK or primary alg provided.");
4087 log_debug("Loading HMAC key into TPM.");
4090 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
4091 * gives you back a different key, the session initiation will fail. In the
4092 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
4093 * provides protections.
4095 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
4096 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
4100 TPM2B_PUBLIC pubkey_tpm2b
;
4101 _cleanup_free_
void *fp
= NULL
;
4104 r
= tpm2_tpm2b_public_from_pem(pubkey
, pubkey_size
, &pubkey_tpm2b
);
4106 return log_error_errno(r
, "Could not create TPMT_PUBLIC: %m");
4108 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
, &fp_size
);
4110 return log_error_errno(r
, "Could not get key fingerprint: %m");
4114 * if a pin is set for the seal object, use it to bind the session
4115 * key to that object. This prevents active bus interposers from
4116 * faking a TPM and seeing the unsealed value. An active interposer
4117 * could fake a TPM, satisfying the encrypted session, and just
4118 * forward everything to the *real* TPM.
4120 r
= tpm2_set_auth(c
, hmac_key
, pin
);
4124 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
4125 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
4129 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
4130 for (unsigned i
= RETRY_UNSEAL_MAX
;; i
--) {
4131 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*policy_session
= NULL
;
4132 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
4133 r
= tpm2_make_policy_session(
4142 r
= tpm2_build_sealing_policy(
4147 pubkey
? &pubkey_tpm2b
: NULL
,
4156 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
4157 * wait until the TPM2 tells us to go away. */
4158 if (known_policy_hash_size
> 0 &&
4159 memcmp_nn(policy_digest
->buffer
, policy_digest
->size
, known_policy_hash
, known_policy_hash_size
) != 0)
4160 return log_error_errno(SYNTHETIC_ERRNO(EPERM
),
4161 "Current policy digest does not match stored policy digest, cancelling "
4162 "TPM2 authentication attempt.");
4164 log_debug("Unsealing HMAC key.");
4166 rc
= sym_Esys_Unseal(
4168 hmac_key
->esys_handle
,
4169 policy_session
->esys_handle
,
4170 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
4173 if (rc
== TSS2_RC_SUCCESS
)
4175 if (rc
!= TPM2_RC_PCR_CHANGED
|| i
== 0)
4176 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4177 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc
));
4178 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i
);
4181 _cleanup_(erase_and_freep
) char *secret
= NULL
;
4182 secret
= memdup(unsealed
->buffer
, unsealed
->size
);
4183 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
4188 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
4190 *ret_secret
= TAKE_PTR(secret
);
4191 *ret_secret_size
= unsealed
->size
;
4198 int tpm2_list_devices(void) {
4200 _cleanup_(table_unrefp
) Table
*t
= NULL
;
4201 _cleanup_closedir_
DIR *d
= NULL
;
4206 return log_error_errno(r
, "TPM2 support is not installed.");
4208 t
= table_new("path", "device", "driver");
4212 d
= opendir("/sys/class/tpmrm");
4214 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
4215 if (errno
!= ENOENT
)
4219 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
4222 de
= readdir_no_dot(d
);
4226 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
4230 r
= readlink_malloc(device_path
, &device
);
4232 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
4234 driver_path
= path_join(device_path
, "driver");
4238 r
= readlink_malloc(driver_path
, &driver
);
4240 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
4243 node
= path_join("/dev", de
->d_name
);
4250 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
4251 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
4253 return table_log_add_error(r
);
4257 if (table_get_rows(t
) <= 1) {
4258 log_info("No suitable TPM2 devices found.");
4262 r
= table_print(t
, stdout
);
4264 return log_error_errno(r
, "Failed to show device table: %m");
4268 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4269 "TPM2 not supported on this build.");
4273 int tpm2_find_device_auto(
4274 int log_level
, /* log level when no device is found */
4277 _cleanup_closedir_
DIR *d
= NULL
;
4282 return log_error_errno(r
, "TPM2 support is not installed.");
4284 d
= opendir("/sys/class/tpmrm");
4286 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
,
4287 "Failed to open /sys/class/tpmrm: %m");
4288 if (errno
!= ENOENT
)
4291 _cleanup_free_
char *node
= NULL
;
4296 de
= readdir_no_dot(d
);
4301 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
4302 "More than one TPM2 (tpmrm) device found.");
4304 node
= path_join("/dev", de
->d_name
);
4310 *ret
= TAKE_PTR(node
);
4315 return log_full_errno(log_level
, SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
4317 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4318 "TPM2 not supported on this build.");
4323 int tpm2_extend_bytes(
4330 size_t secret_size
) {
4333 TPML_DIGEST_VALUES values
= {};
4337 assert(data
|| data_size
== 0);
4338 assert(secret
|| secret_size
== 0);
4340 if (data_size
== SIZE_MAX
)
4341 data_size
= strlen(data
);
4342 if (secret_size
== SIZE_MAX
)
4343 secret_size
= strlen(secret
);
4345 if (pcr_index
>= TPM2_PCRS_MAX
)
4346 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Can't measure into unsupported PCR %u, refusing.", pcr_index
);
4348 if (strv_isempty(banks
))
4351 STRV_FOREACH(bank
, banks
) {
4352 const EVP_MD
*implementation
;
4355 assert_se(implementation
= EVP_get_digestbyname(*bank
));
4357 if (values
.count
>= ELEMENTSOF(values
.digests
))
4358 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
4360 if ((size_t) EVP_MD_size(implementation
) > sizeof(values
.digests
[values
.count
].digest
))
4361 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
), "Hash result too large for TPM2.");
4363 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
4365 return log_error_errno(id
, "Can't map hash name to TPM2.");
4367 values
.digests
[values
.count
].hashAlg
= id
;
4369 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
4370 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
4371 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
4372 * secret for other purposes, maybe because it needs a shorter secret derived from it for
4373 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
4374 * private non-secret string instead. */
4375 if (secret_size
> 0) {
4376 if (!HMAC(implementation
, secret
, secret_size
, data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
))
4377 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to calculate HMAC of data to measure.");
4378 } else if (EVP_Digest(data
, data_size
, (unsigned char*) &values
.digests
[values
.count
].digest
, NULL
, implementation
, NULL
) != 1)
4379 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Failed to hash data to measure.");
4384 rc
= sym_Esys_PCR_Extend(
4386 ESYS_TR_PCR0
+ pcr_index
,
4391 if (rc
!= TSS2_RC_SUCCESS
)
4392 return log_error_errno(
4393 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
4394 "Failed to measure into PCR %u: %s",
4396 sym_Tss2_RC_Decode(rc
));
4399 #else /* HAVE_OPENSSL */
4400 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4405 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
4406 _cleanup_free_
char *s
= NULL
;
4408 FOREACH_PCR_IN_MASK(n
, mask
)
4409 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
4418 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
4419 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
4424 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
4425 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
4427 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
4430 r
= json_variant_new_integer(&e
, i
);
4434 r
= json_variant_append_array(&a
, e
);
4440 return json_variant_new_array(ret
, NULL
, 0);
4446 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
4450 if (!json_variant_is_array(v
))
4451 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
4453 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
4456 if (!json_variant_is_unsigned(e
))
4457 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
4459 u
= json_variant_unsigned(e
);
4460 if (u
>= TPM2_PCRS_MAX
)
4461 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR number out of range: %" PRIu64
, u
);
4463 mask
|= UINT32_C(1) << u
;
4472 int tpm2_make_luks2_json(
4474 uint32_t hash_pcr_mask
,
4478 uint32_t pubkey_pcr_mask
,
4479 uint16_t primary_alg
,
4482 const void *policy_hash
,
4483 size_t policy_hash_size
,
4486 const void *srk_buf
,
4487 size_t srk_buf_size
,
4489 JsonVariant
**ret
) {
4491 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
4492 _cleanup_free_
char *keyslot_as_string
= NULL
;
4495 assert(blob
|| blob_size
== 0);
4496 assert(policy_hash
|| policy_hash_size
== 0);
4497 assert(pubkey
|| pubkey_size
== 0);
4499 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
4502 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
4506 if (pubkey_pcr_mask
!= 0) {
4507 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
4512 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
4513 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
4514 * object should use "_" rather than "-" in field names. */
4518 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
4519 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string
))),
4520 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob
, blob_size
)),
4521 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj
)),
4522 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank
), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank
))),
4523 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg
), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg
))),
4524 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash
, policy_hash_size
)),
4525 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags
& TPM2_FLAGS_USE_PIN
)),
4526 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj
)),
4527 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask
!= 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey
, pubkey_size
)),
4528 JSON_BUILD_PAIR_CONDITION(salt
, "tpm2_salt", JSON_BUILD_BASE64(salt
, salt_size
)),
4529 JSON_BUILD_PAIR_CONDITION(srk_buf
, "tpm2_srk", JSON_BUILD_BASE64(srk_buf
, srk_buf_size
))));
4539 int tpm2_parse_luks2_json(
4542 uint32_t *ret_hash_pcr_mask
,
4543 uint16_t *ret_pcr_bank
,
4545 size_t *ret_pubkey_size
,
4546 uint32_t *ret_pubkey_pcr_mask
,
4547 uint16_t *ret_primary_alg
,
4549 size_t *ret_blob_size
,
4550 void **ret_policy_hash
,
4551 size_t *ret_policy_hash_size
,
4553 size_t *ret_salt_size
,
4555 size_t *ret_srk_buf_size
,
4556 TPM2Flags
*ret_flags
) {
4558 _cleanup_free_
void *blob
= NULL
, *policy_hash
= NULL
, *pubkey
= NULL
, *salt
= NULL
, *srk_buf
= NULL
;
4559 size_t blob_size
= 0, policy_hash_size
= 0, pubkey_size
= 0, salt_size
= 0, srk_buf_size
= 0;
4560 uint32_t hash_pcr_mask
= 0, pubkey_pcr_mask
= 0;
4561 uint16_t primary_alg
= TPM2_ALG_ECC
; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
4562 uint16_t pcr_bank
= UINT16_MAX
; /* default: pick automatically */
4563 int r
, keyslot
= -1;
4564 TPM2Flags flags
= 0;
4570 keyslot
= cryptsetup_get_keyslot_from_token(v
);
4572 /* Return a recognizable error when parsing this field, so that callers can handle parsing
4573 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
4575 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4580 w
= json_variant_by_key(v
, "tpm2-pcrs");
4582 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
4584 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
4586 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
4588 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4590 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
4592 /* The PCR bank field is optional */
4594 if (!json_variant_is_string(w
))
4595 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
4597 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
4599 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
4604 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4605 * the algorithm was hardcoded to ECC. */
4606 w
= json_variant_by_key(v
, "tpm2-primary-alg");
4608 /* The primary key algorithm is optional */
4610 if (!json_variant_is_string(w
))
4611 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
4613 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
4615 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
4620 w
= json_variant_by_key(v
, "tpm2-blob");
4622 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
4624 r
= json_variant_unbase64(w
, &blob
, &blob_size
);
4626 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
4628 w
= json_variant_by_key(v
, "tpm2-policy-hash");
4630 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4632 r
= json_variant_unhex(w
, &policy_hash
, &policy_hash_size
);
4634 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
4636 w
= json_variant_by_key(v
, "tpm2-pin");
4638 if (!json_variant_is_boolean(w
))
4639 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
4641 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
4644 w
= json_variant_by_key(v
, "tpm2_salt");
4646 r
= json_variant_unbase64(w
, &salt
, &salt_size
);
4648 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
4651 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
4653 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
4658 w
= json_variant_by_key(v
, "tpm2_pubkey");
4660 r
= json_variant_unbase64(w
, &pubkey
, &pubkey_size
);
4662 return log_debug_errno(r
, "Failed to decode PCR public key.");
4663 } else if (pubkey_pcr_mask
!= 0)
4664 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4666 w
= json_variant_by_key(v
, "tpm2_srk");
4668 r
= json_variant_unbase64(w
, &srk_buf
, &srk_buf_size
);
4670 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
4674 *ret_keyslot
= keyslot
;
4675 if (ret_hash_pcr_mask
)
4676 *ret_hash_pcr_mask
= hash_pcr_mask
;
4678 *ret_pcr_bank
= pcr_bank
;
4680 *ret_pubkey
= TAKE_PTR(pubkey
);
4681 if (ret_pubkey_size
)
4682 *ret_pubkey_size
= pubkey_size
;
4683 if (ret_pubkey_pcr_mask
)
4684 *ret_pubkey_pcr_mask
= pubkey_pcr_mask
;
4685 if (ret_primary_alg
)
4686 *ret_primary_alg
= primary_alg
;
4688 *ret_blob
= TAKE_PTR(blob
);
4690 *ret_blob_size
= blob_size
;
4691 if (ret_policy_hash
)
4692 *ret_policy_hash
= TAKE_PTR(policy_hash
);
4693 if (ret_policy_hash_size
)
4694 *ret_policy_hash_size
= policy_hash_size
;
4696 *ret_salt
= TAKE_PTR(salt
);
4698 *ret_salt_size
= salt_size
;
4702 *ret_srk_buf
= TAKE_PTR(srk_buf
);
4703 if (ret_srk_buf_size
)
4704 *ret_srk_buf_size
= srk_buf_size
;
4709 int tpm2_hash_alg_to_size(uint16_t alg
) {
4710 if (alg
== TPM2_ALG_SHA1
)
4712 if (alg
== TPM2_ALG_SHA256
)
4714 if (alg
== TPM2_ALG_SHA384
)
4716 if (alg
== TPM2_ALG_SHA512
)
4718 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
4721 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
4722 if (alg
== TPM2_ALG_SHA1
)
4724 if (alg
== TPM2_ALG_SHA256
)
4726 if (alg
== TPM2_ALG_SHA384
)
4728 if (alg
== TPM2_ALG_SHA512
)
4730 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
4734 int tpm2_hash_alg_from_string(const char *alg
) {
4735 if (strcaseeq_ptr(alg
, "sha1"))
4736 return TPM2_ALG_SHA1
;
4737 if (strcaseeq_ptr(alg
, "sha256"))
4738 return TPM2_ALG_SHA256
;
4739 if (strcaseeq_ptr(alg
, "sha384"))
4740 return TPM2_ALG_SHA384
;
4741 if (strcaseeq_ptr(alg
, "sha512"))
4742 return TPM2_ALG_SHA512
;
4743 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm name '%s'", alg
);
4746 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
4747 if (alg
== TPM2_ALG_ECC
)
4749 if (alg
== TPM2_ALG_RSA
)
4751 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
4755 int tpm2_asym_alg_from_string(const char *alg
) {
4756 if (strcaseeq_ptr(alg
, "ecc"))
4757 return TPM2_ALG_ECC
;
4758 if (strcaseeq_ptr(alg
, "rsa"))
4759 return TPM2_ALG_RSA
;
4760 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown asymmetric algorithm name '%s'", alg
);
4763 Tpm2Support
tpm2_support(void) {
4764 Tpm2Support support
= TPM2_SUPPORT_NONE
;
4767 if (detect_container() <= 0) {
4768 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
4769 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
4770 * let's assume containers never have a TPM, at least for now. */
4772 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
4775 log_debug_errno(r
, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
4776 } else if (r
== 0) /* populated! */
4777 support
|= TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_DRIVER
;
4779 /* If the directory exists but is empty, we know the subsystem is enabled but no
4780 * driver has been loaded yet. */
4781 support
|= TPM2_SUPPORT_SUBSYSTEM
;
4785 support
|= TPM2_SUPPORT_FIRMWARE
;
4788 support
|= TPM2_SUPPORT_SYSTEM
;
4792 support
|= TPM2_SUPPORT_LIBRARIES
;
4799 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
4800 TPMI_ALG_HASH default_hash
= 0;
4801 for (size_t i
= 0; i
< n_pcr_values
; i
++)
4802 if (pcr_values
[i
].hash
!= 0) {
4803 default_hash
= pcr_values
[i
].hash
;
4807 if (default_hash
!= 0)
4808 for (size_t i
= 0; i
< n_pcr_values
; i
++)
4809 if (pcr_values
[i
].hash
== 0)
4810 pcr_values
[i
].hash
= default_hash
;
4814 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
4816 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
4817 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
4818 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
4820 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
4821 * tpm2_parse_pcr_argument_append(). */
4822 int tpm2_parse_pcr_argument(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
4827 assert(ret_pcr_values
);
4828 assert(ret_n_pcr_values
);
4830 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
4831 size_t n_pcr_values
= 0;
4832 r
= tpm2_pcr_values_from_string(arg
, &pcr_values
, &n_pcr_values
);
4836 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
4838 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
4840 if (!TPM2_PCR_VALUES_VALID(pcr_values
, n_pcr_values
))
4841 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
4843 *ret_pcr_values
= TAKE_PTR(pcr_values
);
4844 *ret_n_pcr_values
= n_pcr_values
;
4848 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
4852 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
4853 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
4856 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
4857 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
4858 * algorithm check applied again (in case either the previous or current array had no default hash
4859 * algorithm), and then the resulting array is sorted and rechecked for validity. */
4860 int tpm2_parse_pcr_argument_append(const char *arg
, Tpm2PCRValue
**ret_pcr_values
, size_t *ret_n_pcr_values
) {
4865 assert(ret_pcr_values
);
4866 assert(ret_n_pcr_values
);
4868 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
4869 size_t n_pcr_values
;
4870 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
4874 /* If we got previous values, append them. */
4875 if (*ret_pcr_values
&& !GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, *ret_pcr_values
, *ret_n_pcr_values
))
4878 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
4880 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
4882 if (!TPM2_PCR_VALUES_VALID(pcr_values
, n_pcr_values
))
4883 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Parsed PCR values are not valid.");
4885 SWAP_TWO(*ret_pcr_values
, pcr_values
);
4886 *ret_n_pcr_values
= n_pcr_values
;
4890 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
4894 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
4895 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
4896 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
4897 * UINT32_MAX, and or-ing the mask otherwise. */
4898 int tpm2_parse_pcr_argument_to_mask(const char *arg
, uint32_t *ret_mask
) {
4900 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
4901 size_t n_pcr_values
;
4907 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
4911 if (n_pcr_values
== 0) {
4912 /* This retains the previous behavior of clearing the mask if the arg is empty */
4918 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
4920 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
4923 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
4926 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
4928 return log_error_errno(r
, "Could not get pcr values mask: %m");
4930 if (*ret_mask
== UINT32_MAX
)
4931 *ret_mask
= new_mask
;
4933 *ret_mask
|= new_mask
;
4937 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
4941 int tpm2_load_pcr_signature(const char *path
, JsonVariant
**ret
) {
4942 _cleanup_strv_free_
char **search
= NULL
;
4943 _cleanup_free_
char *discovered_path
= NULL
;
4944 _cleanup_fclose_
FILE *f
= NULL
;
4947 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
4948 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4950 search
= strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
4955 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
4956 * this case include /.extra/ in the search path, but only in this case, and if we run in the
4957 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
4959 path
= "tpm2-pcr-signature.json";
4962 if (strv_extend(&search
, "/.extra") < 0)
4966 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
4968 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
4970 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
4972 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
4977 int tpm2_load_pcr_public_key(const char *path
, void **ret_pubkey
, size_t *ret_pubkey_size
) {
4978 _cleanup_free_
char *discovered_path
= NULL
;
4979 _cleanup_fclose_
FILE *f
= NULL
;
4982 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
4983 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4986 path
= "tpm2-pcr-public-key.pem";
4988 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
4990 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
4992 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
4994 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
4999 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
5002 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
5003 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
5004 * I found the wikipedia entry relevant and it contains links to
5006 * - https://en.wikipedia.org/wiki/PBKDF2
5007 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
5009 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
5013 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
5015 uint8_t _cleanup_(erase_and_freep
) *buffer
= NULL
;
5016 uint8_t u
[SHA256_DIGEST_SIZE
];
5018 /* To keep this simple, since derived KeyLen (dkLen in docs)
5019 * Is the same as the hash output, we don't need multiple
5020 * blocks. Part of the algorithm is to add the block count
5021 * in, but this can be hardcoded to 1.
5023 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
5026 assert (saltlen
> 0);
5027 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
5028 assert (passlen
> 0);
5031 * Build a buffer of salt + block_cnt and hmac_sha256 it we
5032 * do this as we don't have a context builder for HMAC_SHA256.
5034 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
5038 memcpy(buffer
, salt
, saltlen
);
5039 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
5041 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
5043 /* dk needs to be an unmodified u as u gets modified in the loop */
5044 memcpy(ret_key
, u
, SHA256_DIGEST_SIZE
);
5045 uint8_t *dk
= ret_key
;
5047 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
5048 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
5050 for (size_t j
=0; j
< sizeof(u
); j
++)
5057 static const char* const pcr_index_table
[_PCR_INDEX_MAX_DEFINED
] = {
5058 [PCR_PLATFORM_CODE
] = "platform-code",
5059 [PCR_PLATFORM_CONFIG
] = "platform-config",
5060 [PCR_EXTERNAL_CODE
] = "external-code",
5061 [PCR_EXTERNAL_CONFIG
] = "external-config",
5062 [PCR_BOOT_LOADER_CODE
] = "boot-loader-code",
5063 [PCR_BOOT_LOADER_CONFIG
] = "boot-loader-config",
5064 [PCR_SECURE_BOOT_POLICY
] = "secure-boot-policy",
5065 [PCR_KERNEL_INITRD
] = "kernel-initrd",
5067 [PCR_KERNEL_BOOT
] = "kernel-boot",
5068 [PCR_KERNEL_CONFIG
] = "kernel-config",
5069 [PCR_SYSEXTS
] = "sysexts",
5070 [PCR_SHIM_POLICY
] = "shim-policy",
5071 [PCR_SYSTEM_IDENTITY
] = "system-identity",
5072 [PCR_DEBUG
] = "debug",
5073 [PCR_APPLICATION_SUPPORT
] = "application-support",
5076 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(pcr_index
, int, TPM2_PCRS_MAX
- 1);
5077 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(pcr_index
, int);