]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/tpm2-util.c
Merge pull request #29601 from yuwata/mmap-check-overflow
[thirdparty/systemd.git] / src / shared / tpm2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <sys/file.h>
4
5 #include "alloc-util.h"
6 #include "constants.h"
7 #include "cryptsetup-util.h"
8 #include "dirent-util.h"
9 #include "dlfcn-util.h"
10 #include "efi-api.h"
11 #include "extract-word.h"
12 #include "fd-util.h"
13 #include "fileio.h"
14 #include "format-table.h"
15 #include "fs-util.h"
16 #include "hexdecoct.h"
17 #include "hmac.h"
18 #include "initrd-util.h"
19 #include "io-util.h"
20 #include "lock-util.h"
21 #include "log.h"
22 #include "logarithm.h"
23 #include "memory-util.h"
24 #include "mkdir.h"
25 #include "nulstr-util.h"
26 #include "parse-util.h"
27 #include "random-util.h"
28 #include "sha256.h"
29 #include "sort-util.h"
30 #include "stat-util.h"
31 #include "string-table.h"
32 #include "sync-util.h"
33 #include "time-util.h"
34 #include "tpm2-util.h"
35 #include "virt.h"
36
37 #if HAVE_TPM2
38 static void *libtss2_esys_dl = NULL;
39 static void *libtss2_rc_dl = NULL;
40 static void *libtss2_mu_dl = NULL;
41
42 static TSS2_RC (*sym_Esys_Create)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, TPM2B_PRIVATE **outPrivate, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
43 static TSS2_RC (*sym_Esys_CreateLoaded)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_TEMPLATE *inPublic, ESYS_TR *objectHandle, TPM2B_PRIVATE **outPrivate, TPM2B_PUBLIC **outPublic) = NULL;
44 static TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR primaryHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, ESYS_TR *objectHandle, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
45 static TSS2_RC (*sym_Esys_EvictControl)(ESYS_CONTEXT *esysContext, ESYS_TR auth, ESYS_TR objectHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMI_DH_PERSISTENT persistentHandle, ESYS_TR *newObjectHandle) = NULL;
46 static void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
47 static TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
48 static void (*sym_Esys_Free)(void *ptr) = NULL;
49 static TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData) = NULL;
50 static TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
51 static TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
52 static TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle) = NULL;
53 static TSS2_RC (*sym_Esys_LoadExternal)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR hierarchy, ESYS_TR *objectHandle) = NULL;
54 static TSS2_RC (*sym_Esys_PCR_Extend)(ESYS_CONTEXT *esysContext, ESYS_TR pcrHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST_VALUES *digests) = NULL;
55 static TSS2_RC (*sym_Esys_PCR_Read)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1,ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues) = NULL;
56 static TSS2_RC (*sym_Esys_PolicyAuthorize)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *approvedPolicy, const TPM2B_NONCE *policyRef, const TPM2B_NAME *keySign, const TPMT_TK_VERIFIED *checkTicket) = NULL;
57 static TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
58 static TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
59 static TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL;
60 static TSS2_RC (*sym_Esys_ReadPublic)(ESYS_CONTEXT *esysContext, ESYS_TR objectHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_PUBLIC **outPublic, TPM2B_NAME **name, TPM2B_NAME **qualifiedName) = NULL;
61 static TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL;
62 static TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
63 static TSS2_RC (*sym_Esys_TestParms)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPMT_PUBLIC_PARMS *parameters) = NULL;
64 static TSS2_RC (*sym_Esys_TR_Close)(ESYS_CONTEXT *esys_context, ESYS_TR *rsrc_handle) = NULL;
65 static TSS2_RC (*sym_Esys_TR_Deserialize)(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle) = NULL;
66 static TSS2_RC (*sym_Esys_TR_FromTPMPublic)(ESYS_CONTEXT *esysContext, TPM2_HANDLE tpm_handle, ESYS_TR optionalSession1, ESYS_TR optionalSession2, ESYS_TR optionalSession3, ESYS_TR *object) = NULL;
67 static TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name) = NULL;
68 static TSS2_RC (*sym_Esys_TR_GetTpmHandle)(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, TPM2_HANDLE *tpm_handle) = NULL;
69 static TSS2_RC (*sym_Esys_TR_Serialize)(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size) = NULL;
70 static TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
71 static TSS2_RC (*sym_Esys_TRSess_GetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION *flags) = NULL;
72 static TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask) = NULL;
73 static TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
74 static TSS2_RC (*sym_Esys_VerifySignature)(ESYS_CONTEXT *esysContext, ESYS_TR keyHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *digest, const TPMT_SIGNATURE *signature, TPMT_TK_VERIFIED **validation) = NULL;
75
76 static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal)(TPM2_CC src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
77 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
78 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
79 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
80 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
81 static TSS2_RC (*sym_Tss2_MU_TPML_PCR_SELECTION_Marshal)(TPML_PCR_SELECTION const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
82 static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal)(TPMT_HA const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
83 static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal)(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
84
85 static const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
86
87 int dlopen_tpm2(void) {
88 int r;
89
90 r = dlopen_many_sym_or_warn(
91 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
92 DLSYM_ARG(Esys_Create),
93 DLSYM_ARG(Esys_CreateLoaded),
94 DLSYM_ARG(Esys_CreatePrimary),
95 DLSYM_ARG(Esys_EvictControl),
96 DLSYM_ARG(Esys_Finalize),
97 DLSYM_ARG(Esys_FlushContext),
98 DLSYM_ARG(Esys_Free),
99 DLSYM_ARG(Esys_GetCapability),
100 DLSYM_ARG(Esys_GetRandom),
101 DLSYM_ARG(Esys_Initialize),
102 DLSYM_ARG(Esys_Load),
103 DLSYM_ARG(Esys_LoadExternal),
104 DLSYM_ARG(Esys_PCR_Extend),
105 DLSYM_ARG(Esys_PCR_Read),
106 DLSYM_ARG(Esys_PolicyAuthorize),
107 DLSYM_ARG(Esys_PolicyAuthValue),
108 DLSYM_ARG(Esys_PolicyGetDigest),
109 DLSYM_ARG(Esys_PolicyPCR),
110 DLSYM_ARG(Esys_ReadPublic),
111 DLSYM_ARG(Esys_StartAuthSession),
112 DLSYM_ARG(Esys_Startup),
113 DLSYM_ARG(Esys_TestParms),
114 DLSYM_ARG(Esys_TR_Close),
115 DLSYM_ARG(Esys_TR_Deserialize),
116 DLSYM_ARG(Esys_TR_FromTPMPublic),
117 DLSYM_ARG(Esys_TR_GetName),
118 DLSYM_ARG(Esys_TR_Serialize),
119 DLSYM_ARG(Esys_TR_SetAuth),
120 DLSYM_ARG(Esys_TRSess_GetAttributes),
121 DLSYM_ARG(Esys_TRSess_SetAttributes),
122 DLSYM_ARG(Esys_Unseal),
123 DLSYM_ARG(Esys_VerifySignature));
124 if (r < 0)
125 return r;
126
127 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
128 * version of 2.4.0 this sym can be moved up to the normal list above. */
129 r = dlsym_many_or_warn(libtss2_esys_dl, LOG_DEBUG, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle));
130 if (r < 0)
131 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
132
133 r = dlopen_many_sym_or_warn(
134 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
135 DLSYM_ARG(Tss2_RC_Decode));
136 if (r < 0)
137 return r;
138
139 return dlopen_many_sym_or_warn(
140 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
141 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
142 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
143 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
144 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
145 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
146 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal),
147 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal),
148 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal));
149 }
150
151 void Esys_Freep(void *p) {
152 if (*(void**) p)
153 sym_Esys_Free(*(void**) p);
154 }
155
156 /* Get a specific TPM capability (or capabilities).
157 *
158 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
159 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
160 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
161 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
162 *
163 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
164 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
165 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
166 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
167 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
168 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
169 * capability category may have more specific requirements than described here; see the spec for exact
170 * details. */
171 static int tpm2_get_capability(
172 Tpm2Context *c,
173 TPM2_CAP capability,
174 uint32_t property,
175 uint32_t count,
176 TPMU_CAPABILITIES *ret_capability_data) {
177
178 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *capabilities = NULL;
179 TPMI_YES_NO more;
180 TSS2_RC rc;
181
182 assert(c);
183
184 log_debug("Getting TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " count %" PRIu32 ".",
185 capability, property, count);
186
187 rc = sym_Esys_GetCapability(
188 c->esys_context,
189 ESYS_TR_NONE,
190 ESYS_TR_NONE,
191 ESYS_TR_NONE,
192 capability,
193 property,
194 count,
195 &more,
196 &capabilities);
197 if (rc != TSS2_RC_SUCCESS)
198 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
199 "Failed to get TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 ": %s",
200 capability, property, sym_Tss2_RC_Decode(rc));
201
202 if (capabilities->capability != capability)
203 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
204 "TPM provided wrong capability: 0x%04" PRIx32 " instead of 0x%04" PRIx32 ".",
205 capabilities->capability, capability);
206
207 if (ret_capability_data)
208 *ret_capability_data = capabilities->data;
209
210 return more == TPM2_YES;
211 }
212
213 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
214
215 static int tpm2_cache_capabilities(Tpm2Context *c) {
216 TPMU_CAPABILITIES capability;
217 int r;
218
219 assert(c);
220
221 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
222 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
223 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
224 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
225 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
226 * changed while we are performing some operation, it's reasonable to assume it will break us even if
227 * we don't cache the algorithms, thus they should be "safe" to cache. */
228 TPM2_ALG_ID current_alg = TPM2_ALG_FIRST;
229 for (;;) {
230 r = tpm2_get_capability(
231 c,
232 TPM2_CAP_ALGS,
233 (uint32_t) current_alg, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
234 TPM2_MAX_CAP_ALGS,
235 &capability);
236 if (r < 0)
237 return r;
238
239 TPML_ALG_PROPERTY algorithms = capability.algorithms;
240
241 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
242 * there are no more. */
243 assert(algorithms.count > 0);
244
245 if (!GREEDY_REALLOC_APPEND(
246 c->capability_algorithms,
247 c->n_capability_algorithms,
248 algorithms.algProperties,
249 algorithms.count))
250 return log_oom_debug();
251
252 if (r == 0)
253 break;
254
255 /* Set current_alg to alg id after last alg id the TPM provided */
256 current_alg = algorithms.algProperties[algorithms.count - 1].alg + 1;
257 }
258
259 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
260 * while running, but that would be crazy, so let's hope it is not possible. */
261 TPM2_CC current_cc = TPM2_CC_FIRST;
262 for (;;) {
263 r = tpm2_get_capability(
264 c,
265 TPM2_CAP_COMMANDS,
266 current_cc,
267 TPM2_MAX_CAP_CC,
268 &capability);
269 if (r < 0)
270 return r;
271
272 TPML_CCA commands = capability.command;
273
274 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
275 * there are no more. */
276 assert(commands.count > 0);
277
278 if (!GREEDY_REALLOC_APPEND(
279 c->capability_commands,
280 c->n_capability_commands,
281 commands.commandAttributes,
282 commands.count))
283 return log_oom_debug();
284
285 if (r == 0)
286 break;
287
288 /* Set current_cc to index after last cc the TPM provided */
289 current_cc = TPMA_CC_TO_TPM2_CC(commands.commandAttributes[commands.count - 1]) + 1;
290 }
291
292 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
293 * while running, but that would be crazy, so let's hope it is not possible. */
294 TPM2_ECC_CURVE current_ecc_curve = TPM2_ECC_NONE;
295 for (;;) {
296 r = tpm2_get_capability(
297 c,
298 TPM2_CAP_ECC_CURVES,
299 current_ecc_curve,
300 TPM2_MAX_ECC_CURVES,
301 &capability);
302 if (r < 0)
303 return r;
304
305 TPML_ECC_CURVE ecc_curves = capability.eccCurves;
306
307 /* ECC support isn't required */
308 if (ecc_curves.count == 0)
309 break;
310
311 if (!GREEDY_REALLOC_APPEND(
312 c->capability_ecc_curves,
313 c->n_capability_ecc_curves,
314 ecc_curves.eccCurves,
315 ecc_curves.count))
316 return log_oom_debug();
317
318 if (r == 0)
319 break;
320
321 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
322 current_ecc_curve = ecc_curves.eccCurves[ecc_curves.count - 1] + 1;
323 }
324
325 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
326 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
327 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
328 * safely assume the TPM PCR allocation will not change while we are using it. */
329 r = tpm2_get_capability(
330 c,
331 TPM2_CAP_PCRS,
332 /* property= */ 0,
333 /* count= */ 1,
334 &capability);
335 if (r < 0)
336 return r;
337 if (r == 1)
338 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
339 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
340 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
341 * this command with the full PCR allocation and moreData will be NO." */
342 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
343 c->capability_pcrs = capability.assignedPCR;
344
345 return 0;
346 }
347
348 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
349 * TPMA_ALGORITHM is provided, otherwise false. */
350 static bool tpm2_get_capability_alg(Tpm2Context *c, TPM2_ALG_ID alg, TPMA_ALGORITHM *ret) {
351 assert(c);
352
353 FOREACH_ARRAY(alg_prop, c->capability_algorithms, c->n_capability_algorithms)
354 if (alg_prop->alg == alg) {
355 if (ret)
356 *ret = alg_prop->algProperties;
357 return true;
358 }
359
360 log_debug("TPM does not support alg 0x%02" PRIx16 ".", alg);
361 if (ret)
362 *ret = 0;
363
364 return false;
365 }
366
367 bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg) {
368 return tpm2_get_capability_alg(c, alg, NULL);
369 }
370
371 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
372 * otherwise false. */
373 static bool tpm2_get_capability_command(Tpm2Context *c, TPM2_CC command, TPMA_CC *ret) {
374 assert(c);
375
376 FOREACH_ARRAY(cca, c->capability_commands, c->n_capability_commands)
377 if (TPMA_CC_TO_TPM2_CC(*cca) == command) {
378 if (ret)
379 *ret = *cca;
380 return true;
381 }
382
383 log_debug("TPM does not support command 0x%04" PRIx32 ".", command);
384 if (ret)
385 *ret = 0;
386
387 return false;
388 }
389
390 bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command) {
391 return tpm2_get_capability_command(c, command, NULL);
392 }
393
394 /* Returns true if the TPM supports the ECC curve, otherwise false. */
395 bool tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE ecc_curve) {
396 assert(c);
397
398 FOREACH_ARRAY(curve, c->capability_ecc_curves, c->n_capability_ecc_curves)
399 if (*curve == ecc_curve)
400 return true;
401
402 log_debug("TPM does not support ECC curve 0x%" PRIx16 ".", ecc_curve);
403 return false;
404 }
405
406 /* Query the TPM for populated handles.
407 *
408 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
409 * contain only populated handle addresses (which might not include the requested handle). The number of
410 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
411 * range (i.e. handle & 0xff000000).
412 *
413 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
414 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
415 static int tpm2_get_capability_handles(
416 Tpm2Context *c,
417 TPM2_HANDLE start,
418 size_t max,
419 TPM2_HANDLE **ret_handles,
420 size_t *ret_n_handles) {
421
422 _cleanup_free_ TPM2_HANDLE *handles = NULL;
423 size_t n_handles = 0;
424 TPM2_HANDLE current = start;
425 int r = 0;
426
427 assert(c);
428 assert(ret_handles);
429 assert(ret_n_handles);
430
431 max = MIN(max, UINT32_MAX);
432
433 while (max > 0) {
434 TPMU_CAPABILITIES capability;
435 r = tpm2_get_capability(c, TPM2_CAP_HANDLES, current, (uint32_t) max, &capability);
436 if (r < 0)
437 return r;
438
439 TPML_HANDLE handle_list = capability.handles;
440 if (handle_list.count == 0)
441 break;
442
443 assert(handle_list.count <= max);
444
445 if (n_handles > SIZE_MAX - handle_list.count)
446 return log_oom_debug();
447
448 if (!GREEDY_REALLOC_APPEND(handles, n_handles, handle_list.handle, handle_list.count))
449 return log_oom_debug();
450
451 max -= handle_list.count;
452
453 /* Update current to the handle index after the last handle in the list. */
454 current = handles[n_handles - 1] + 1;
455
456 if (r == 0)
457 /* No more handles in this range. */
458 break;
459 }
460
461 *ret_handles = TAKE_PTR(handles);
462 *ret_n_handles = n_handles;
463
464 return r;
465 }
466
467 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
468 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
469
470 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
471 static int tpm2_get_capability_handle(Tpm2Context *c, TPM2_HANDLE handle) {
472 _cleanup_free_ TPM2_HANDLE *handles = NULL;
473 size_t n_handles = 0;
474 int r;
475
476 r = tpm2_get_capability_handles(c, handle, 1, &handles, &n_handles);
477 if (r < 0)
478 return r;
479
480 return n_handles == 0 ? false : handles[0] == handle;
481 }
482
483 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
484 bool tpm2_test_parms(Tpm2Context *c, TPMI_ALG_PUBLIC alg, const TPMU_PUBLIC_PARMS *parms) {
485 TSS2_RC rc;
486
487 assert(c);
488 assert(parms);
489
490 TPMT_PUBLIC_PARMS parameters = {
491 .type = alg,
492 .parameters = *parms,
493 };
494
495 rc = sym_Esys_TestParms(c->esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parameters);
496 if (rc != TSS2_RC_SUCCESS)
497 /* The spec says if the parms are not supported the TPM returns "...the appropriate
498 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
499 * unmarshaling errors, instead of checking for them all here, let's just assume any error
500 * indicates unsupported parms, and log the specific error text. */
501 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc));
502
503 return rc == TSS2_RC_SUCCESS;
504 }
505
506 static bool tpm2_supports_tpmt_public(Tpm2Context *c, const TPMT_PUBLIC *public) {
507 assert(c);
508 assert(public);
509
510 return tpm2_test_parms(c, public->type, &public->parameters);
511 }
512
513 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context *c, const TPMT_SYM_DEF_OBJECT *parameters) {
514 assert(c);
515 assert(parameters);
516
517 TPMU_PUBLIC_PARMS parms = {
518 .symDetail.sym = *parameters,
519 };
520
521 return tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms);
522 }
523
524 static bool tpm2_supports_tpmt_sym_def(Tpm2Context *c, const TPMT_SYM_DEF *parameters) {
525 assert(c);
526 assert(parameters);
527
528 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
529 * functionally identical. */
530 TPMT_SYM_DEF_OBJECT object = {
531 .algorithm = parameters->algorithm,
532 .keyBits = parameters->keyBits,
533 .mode = parameters->mode,
534 };
535
536 return tpm2_supports_tpmt_sym_def_object(c, &object);
537 }
538
539 static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
540 if (!c)
541 return NULL;
542
543 if (c->esys_context)
544 sym_Esys_Finalize(&c->esys_context);
545
546 c->tcti_context = mfree(c->tcti_context);
547 c->tcti_dl = safe_dlclose(c->tcti_dl);
548
549 c->capability_algorithms = mfree(c->capability_algorithms);
550 c->capability_commands = mfree(c->capability_commands);
551 c->capability_ecc_curves = mfree(c->capability_ecc_curves);
552
553 return mfree(c);
554 }
555
556 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
557
558 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB = {
559 .algorithm = TPM2_ALG_AES,
560 .keyBits.aes = 128,
561 .mode.aes = TPM2_ALG_CFB, /* The spec requires sessions to use CFB. */
562 };
563
564 int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
565 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = NULL;
566 TSS2_RC rc;
567 int r;
568
569 assert(ret_context);
570
571 context = new(Tpm2Context, 1);
572 if (!context)
573 return log_oom_debug();
574
575 *context = (Tpm2Context) {
576 .n_ref = 1,
577 };
578
579 r = dlopen_tpm2();
580 if (r < 0)
581 return log_debug_errno(r, "TPM2 support not installed: %m");
582
583 if (!device) {
584 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
585 if (device)
586 /* Setting the env var to an empty string forces tpm2-tss' own device picking
587 * logic to be used. */
588 device = empty_to_null(device);
589 else
590 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
591 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
592 * might be used and we really don't want that, since it is a system service and that creates
593 * various ordering issues/deadlocks during early boot. */
594 device = "device:/dev/tpmrm0";
595 }
596
597 if (device) {
598 const char *param, *driver, *fn;
599 const TSS2_TCTI_INFO* info;
600 TSS2_TCTI_INFO_FUNC func;
601 size_t sz = 0;
602
603 param = strchr(device, ':');
604 if (param) {
605 /* Syntax #1: Pair of driver string and arbitrary parameter */
606 driver = strndupa_safe(device, param - device);
607 if (isempty(driver))
608 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
609
610 param++;
611 } else if (path_is_absolute(device) && path_is_valid(device)) {
612 /* Syntax #2: TPM device node */
613 driver = "device";
614 param = device;
615 } else
616 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
617
618 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
619
620 fn = strjoina("libtss2-tcti-", driver, ".so.0");
621
622 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
623 if (!filename_is_valid(fn))
624 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
625
626 context->tcti_dl = dlopen(fn, RTLD_NOW);
627 if (!context->tcti_dl)
628 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
629
630 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
631 if (!func)
632 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
633 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
634 dlerror());
635
636 info = func();
637 if (!info)
638 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
639
640 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
641
642 rc = info->init(NULL, &sz, NULL);
643 if (rc != TPM2_RC_SUCCESS)
644 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
645 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
646
647 context->tcti_context = malloc0(sz);
648 if (!context->tcti_context)
649 return log_oom_debug();
650
651 rc = info->init(context->tcti_context, &sz, param);
652 if (rc != TPM2_RC_SUCCESS)
653 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
654 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
655 }
656
657 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
658 if (rc != TSS2_RC_SUCCESS)
659 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
660 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
661
662 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
663 if (rc == TPM2_RC_INITIALIZE)
664 log_debug("TPM already started up.");
665 else if (rc == TSS2_RC_SUCCESS)
666 log_debug("TPM successfully started up.");
667 else
668 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
669 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
670
671 r = tpm2_cache_capabilities(context);
672 if (r < 0)
673 return log_debug_errno(r, "Failed to cache TPM capabilities: %m");
674
675 /* We require AES and CFB support for session encryption. */
676 if (!tpm2_supports_alg(context, TPM2_ALG_AES))
677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES.");
678
679 if (!tpm2_supports_alg(context, TPM2_ALG_CFB))
680 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support CFB.");
681
682 if (!tpm2_supports_tpmt_sym_def(context, &SESSION_TEMPLATE_SYM_AES_128_CFB))
683 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES-128-CFB.");
684
685 *ret_context = TAKE_PTR(context);
686
687 return 0;
688 }
689
690 static void tpm2_handle_cleanup(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, bool flush) {
691 TSS2_RC rc;
692
693 if (!esys_context || esys_handle == ESYS_TR_NONE)
694 return;
695
696 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
697 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
698 * as removing its corresponding handle from the actual TPM. */
699 if (flush)
700 rc = sym_Esys_FlushContext(esys_context, esys_handle);
701 else
702 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
703 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
704 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
705 * directly affects us; for example the src/test/test-tpm2.c test function
706 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
707 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
708 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
709 * references will be cleaned up when we free our ESYS_CONTEXT.
710 *
711 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
712 rc = TSS2_RC_SUCCESS; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
713 if (rc != TSS2_RC_SUCCESS)
714 /* We ignore failures here (besides debug logging), since this is called in error paths,
715 * where we cannot do anything about failures anymore. And when it is called in successful
716 * codepaths by this time we already did what we wanted to do, and got the results we wanted
717 * so there's no reason to make this fail more loudly than necessary. */
718 log_debug("Failed to %s TPM handle, ignoring: %s", flush ? "flush" : "close", sym_Tss2_RC_Decode(rc));
719 }
720
721 Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
722 if (!handle)
723 return NULL;
724
725 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
726 if (context)
727 tpm2_handle_cleanup(context->esys_context, handle->esys_handle, handle->flush);
728
729 return mfree(handle);
730 }
731
732 int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
733 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
734
735 assert(ret_handle);
736
737 handle = new(Tpm2Handle, 1);
738 if (!handle)
739 return log_oom_debug();
740
741 *handle = (Tpm2Handle) {
742 .tpm2_context = tpm2_context_ref(context),
743 .esys_handle = ESYS_TR_NONE,
744 .flush = true,
745 };
746
747 *ret_handle = TAKE_PTR(handle);
748
749 return 0;
750 }
751
752 static int tpm2_read_public(
753 Tpm2Context *c,
754 const Tpm2Handle *session,
755 const Tpm2Handle *handle,
756 TPM2B_PUBLIC **ret_public,
757 TPM2B_NAME **ret_name,
758 TPM2B_NAME **ret_qname) {
759
760 TSS2_RC rc;
761
762 assert(c);
763 assert(handle);
764
765 rc = sym_Esys_ReadPublic(
766 c->esys_context,
767 handle->esys_handle,
768 session ? session->esys_handle : ESYS_TR_NONE,
769 ESYS_TR_NONE,
770 ESYS_TR_NONE,
771 ret_public,
772 ret_name,
773 ret_qname);
774 if (rc != TSS2_RC_SUCCESS)
775 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
776 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
777
778 return 0;
779 }
780
781 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
782 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
783 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
784 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
785 * Tpm2Handle. */
786 int tpm2_index_to_handle(
787 Tpm2Context *c,
788 TPM2_HANDLE index,
789 const Tpm2Handle *session,
790 TPM2B_PUBLIC **ret_public,
791 TPM2B_NAME **ret_name,
792 TPM2B_NAME **ret_qname,
793 Tpm2Handle **ret_handle) {
794
795 TSS2_RC rc;
796 int r;
797
798 assert(c);
799
800 /* Only allow persistent, transient, or NV index handle types. */
801 switch (TPM2_HANDLE_TYPE(index)) {
802 case TPM2_HT_PERSISTENT:
803 case TPM2_HT_NV_INDEX:
804 case TPM2_HT_TRANSIENT:
805 break;
806 case TPM2_HT_PCR:
807 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
808 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
809 "Invalid handle 0x%08" PRIx32 " (in PCR range).", index);
810 case TPM2_HT_HMAC_SESSION:
811 case TPM2_HT_POLICY_SESSION:
812 /* Session indexes are only used internally by tpm2-tss (or lower code) */
813 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
814 "Invalid handle 0x%08" PRIx32 " (in session range).", index);
815 case TPM2_HT_PERMANENT:
816 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
817 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
818 "Invalid handle 0x%08" PRIx32 " (in permanent range).", index);
819 default:
820 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
821 "Invalid handle 0x%08" PRIx32 " (in unknown range).", index);
822 }
823
824 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
825 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
826 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
827 if (TPM2_HANDLE_TYPE(index) != TPM2_HT_TRANSIENT) { // FIXME: once kernel bug is fixed, check transient handles too
828 r = tpm2_get_capability_handle(c, index);
829 if (r < 0)
830 return r;
831 if (r == 0) {
832 log_debug("TPM handle 0x%08" PRIx32 " not populated.", index);
833 if (ret_public)
834 *ret_public = NULL;
835 if (ret_name)
836 *ret_name = NULL;
837 if (ret_qname)
838 *ret_qname = NULL;
839 if (ret_handle)
840 *ret_handle = NULL;
841 return 0;
842 }
843 }
844
845 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
846 r = tpm2_handle_new(c, &handle);
847 if (r < 0)
848 return r;
849
850 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
851 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
852 handle->flush = false;
853
854 rc = sym_Esys_TR_FromTPMPublic(
855 c->esys_context,
856 index,
857 session ? session->esys_handle : ESYS_TR_NONE,
858 ESYS_TR_NONE,
859 ESYS_TR_NONE,
860 &handle->esys_handle);
861 if (rc != TSS2_RC_SUCCESS)
862 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
863 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
864
865 if (ret_public || ret_name || ret_qname) {
866 r = tpm2_read_public(c, session, handle, ret_public, ret_name, ret_qname);
867 if (r < 0)
868 return r;
869 }
870
871 if (ret_handle)
872 *ret_handle = TAKE_PTR(handle);
873
874 return 1;
875 }
876
877 /* Get the handle index for the provided Tpm2Handle. */
878 int tpm2_index_from_handle(Tpm2Context *c, const Tpm2Handle *handle, TPM2_HANDLE *ret_index) {
879 TSS2_RC rc;
880
881 assert(c);
882 assert(handle);
883 assert(ret_index);
884
885 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
886 * version of 2.4.0 this check can be removed. */
887 if (!sym_Esys_TR_GetTpmHandle)
888 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
889 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
890
891 rc = sym_Esys_TR_GetTpmHandle(c->esys_context, handle->esys_handle, ret_index);
892 if (rc != TSS2_RC_SUCCESS)
893 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
894 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc));
895
896 return 0;
897 }
898
899 /* Copy an object in the TPM at a transient handle to a persistent handle.
900 *
901 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
902 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
903 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
904 * be used.
905 *
906 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
907 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
908 * at the requested persistent handle index (or the first available if none was requested).
909 *
910 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
911 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
912 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
913 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
914 * memory for persistent storage. The persistent handle is only provided when returning 1. */
915 static int tpm2_persist_handle(
916 Tpm2Context *c,
917 const Tpm2Handle *transient_handle,
918 const Tpm2Handle *session,
919 TPMI_DH_PERSISTENT persistent_handle_index,
920 Tpm2Handle **ret_persistent_handle) {
921
922 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
923 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
924 TPMI_DH_PERSISTENT first = UINT32_C(0x81000000), last = UINT32_C(0x81ffffff);
925 TSS2_RC rc;
926 int r;
927
928 assert(c);
929 assert(transient_handle);
930
931 /* If persistent handle index specified, only try that. */
932 if (persistent_handle_index != 0) {
933 if (TPM2_HANDLE_TYPE(persistent_handle_index) != TPM2_HT_PERSISTENT)
934 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
935 "Handle not in persistent range: 0x%x", persistent_handle_index);
936
937 first = last = persistent_handle_index;
938 }
939
940 for (TPMI_DH_PERSISTENT requested = first; requested <= last; requested++) {
941 _cleanup_(tpm2_handle_freep) Tpm2Handle *persistent_handle = NULL;
942 r = tpm2_handle_new(c, &persistent_handle);
943 if (r < 0)
944 return r;
945
946 /* Since this is a persistent handle, don't flush it. */
947 persistent_handle->flush = false;
948
949 rc = sym_Esys_EvictControl(
950 c->esys_context,
951 ESYS_TR_RH_OWNER,
952 transient_handle->esys_handle,
953 session ? session->esys_handle : ESYS_TR_PASSWORD,
954 ESYS_TR_NONE,
955 ESYS_TR_NONE,
956 requested,
957 &persistent_handle->esys_handle);
958 if (rc == TSS2_RC_SUCCESS) {
959 if (ret_persistent_handle)
960 *ret_persistent_handle = TAKE_PTR(persistent_handle);
961
962 return 1;
963 }
964 if (rc != TPM2_RC_NV_DEFINED)
965 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
966 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc));
967 }
968
969 if (ret_persistent_handle)
970 *ret_persistent_handle = NULL;
971
972 return 0;
973 }
974
975 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
976
977 static int tpm2_credit_random(Tpm2Context *c) {
978 size_t rps, done = 0;
979 TSS2_RC rc;
980 usec_t t;
981 int r;
982
983 assert(c);
984
985 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
986 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
987 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
988 * any entropy. */
989
990 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
991 if (errno != ENOENT)
992 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
993 } else {
994 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
995 return 0; /* Already done */
996 }
997
998 t = now(CLOCK_MONOTONIC);
999
1000 for (rps = random_pool_size(); rps > 0;) {
1001 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
1002
1003 rc = sym_Esys_GetRandom(
1004 c->esys_context,
1005 ESYS_TR_NONE,
1006 ESYS_TR_NONE,
1007 ESYS_TR_NONE,
1008 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1009 &buffer);
1010 if (rc != TSS2_RC_SUCCESS)
1011 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1012 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
1013
1014 if (buffer->size == 0)
1015 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1016 "Zero-sized entropy returned from TPM.");
1017
1018 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
1019 if (r < 0)
1020 return log_debug_errno(r, "Failed wo write entropy to kernel: %m");
1021
1022 done += buffer->size;
1023 rps = LESS_BY(rps, buffer->size);
1024 }
1025
1026 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
1027
1028 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
1029 if (r < 0)
1030 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
1031
1032 return 0;
1033 }
1034
1035 /* Get one of the legacy primary key templates.
1036 *
1037 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1038 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1039 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1040 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1041 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1042 /* Do not modify. */
1043 static const TPMT_PUBLIC legacy_ecc = {
1044 .type = TPM2_ALG_ECC,
1045 .nameAlg = TPM2_ALG_SHA256,
1046 .objectAttributes =
1047 TPMA_OBJECT_RESTRICTED|
1048 TPMA_OBJECT_DECRYPT|
1049 TPMA_OBJECT_FIXEDTPM|
1050 TPMA_OBJECT_FIXEDPARENT|
1051 TPMA_OBJECT_SENSITIVEDATAORIGIN|
1052 TPMA_OBJECT_USERWITHAUTH,
1053 .parameters.eccDetail = {
1054 .symmetric = {
1055 .algorithm = TPM2_ALG_AES,
1056 .keyBits.aes = 128,
1057 .mode.aes = TPM2_ALG_CFB,
1058 },
1059 .scheme.scheme = TPM2_ALG_NULL,
1060 .curveID = TPM2_ECC_NIST_P256,
1061 .kdf.scheme = TPM2_ALG_NULL,
1062 },
1063 };
1064
1065 /* Do not modify. */
1066 static const TPMT_PUBLIC legacy_rsa = {
1067 .type = TPM2_ALG_RSA,
1068 .nameAlg = TPM2_ALG_SHA256,
1069 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
1070 .parameters.rsaDetail = {
1071 .symmetric = {
1072 .algorithm = TPM2_ALG_AES,
1073 .keyBits.aes = 128,
1074 .mode.aes = TPM2_ALG_CFB,
1075 },
1076 .scheme.scheme = TPM2_ALG_NULL,
1077 .keyBits = 2048,
1078 },
1079 };
1080
1081 assert(ret_template);
1082
1083 if (alg == TPM2_ALG_ECC)
1084 *ret_template = legacy_ecc;
1085 else if (alg == TPM2_ALG_RSA)
1086 *ret_template = legacy_rsa;
1087 else
1088 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1089 "Unsupported legacy SRK alg: 0x%x", alg);
1090
1091 return 0;
1092 }
1093
1094 /* Get a Storage Root Key (SRK) template.
1095 *
1096 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1097 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1098 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1099 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1100 * "L-2" (for ECC).
1101 *
1102 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1103 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1104 *
1105 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1106 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1107 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1108 *
1109 * The alg must be TPM2_ALG_RSA or TPM2_ALG_ECC. Returns error if the requested template is not supported on
1110 * this TPM. Also see tpm2_get_best_srk_template() below. */
1111 static int tpm2_get_srk_template(Tpm2Context *c, TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1112 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1113 * Provisioning Guidance document, specifically:
1114 * TPMA_OBJECT_USERWITHAUTH is added.
1115 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1116 * TPMA_OBJECT_NODA is added. */
1117 TPMA_OBJECT srk_attributes =
1118 TPMA_OBJECT_DECRYPT |
1119 TPMA_OBJECT_FIXEDPARENT |
1120 TPMA_OBJECT_FIXEDTPM |
1121 TPMA_OBJECT_NODA |
1122 TPMA_OBJECT_RESTRICTED |
1123 TPMA_OBJECT_SENSITIVEDATAORIGIN |
1124 TPMA_OBJECT_USERWITHAUTH;
1125
1126 /* The symmetric configuration is the same between ECC and RSA templates. */
1127 TPMT_SYM_DEF_OBJECT srk_symmetric = {
1128 .algorithm = TPM2_ALG_AES,
1129 .keyBits.aes = 128,
1130 .mode.aes = TPM2_ALG_CFB,
1131 };
1132
1133 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1134
1135 /* From the EK Credential Profile template "L-2". */
1136 TPMT_PUBLIC srk_ecc = {
1137 .type = TPM2_ALG_ECC,
1138 .nameAlg = TPM2_ALG_SHA256,
1139 .objectAttributes = srk_attributes,
1140 .parameters.eccDetail = {
1141 .symmetric = srk_symmetric,
1142 .scheme.scheme = TPM2_ALG_NULL,
1143 .curveID = TPM2_ECC_NIST_P256,
1144 .kdf.scheme = TPM2_ALG_NULL,
1145 },
1146 };
1147
1148 /* From the EK Credential Profile template "L-1". */
1149 TPMT_PUBLIC srk_rsa = {
1150 .type = TPM2_ALG_RSA,
1151 .nameAlg = TPM2_ALG_SHA256,
1152 .objectAttributes = srk_attributes,
1153 .parameters.rsaDetail = {
1154 .symmetric = srk_symmetric,
1155 .scheme.scheme = TPM2_ALG_NULL,
1156 .keyBits = 2048,
1157 },
1158 };
1159
1160 assert(c);
1161 assert(ret_template);
1162
1163 if (alg == TPM2_ALG_ECC) {
1164 if (!tpm2_supports_alg(c, TPM2_ALG_ECC))
1165 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1166 "TPM does not support ECC.");
1167
1168 if (!tpm2_supports_ecc_curve(c, srk_ecc.parameters.eccDetail.curveID))
1169 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1170 "TPM does not support ECC-NIST-P256 curve.");
1171
1172 if (!tpm2_supports_tpmt_public(c, &srk_ecc))
1173 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1174 "TPM does not support SRK ECC template L-2.");
1175
1176 *ret_template = srk_ecc;
1177 return 0;
1178 }
1179
1180 if (alg == TPM2_ALG_RSA) {
1181 if (!tpm2_supports_alg(c, TPM2_ALG_RSA))
1182 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1183 "TPM does not support RSA.");
1184
1185 if (!tpm2_supports_tpmt_public(c, &srk_rsa))
1186 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1187 "TPM does not support SRK RSA template L-1.");
1188
1189 *ret_template = srk_rsa;
1190 return 0;
1191 }
1192
1193 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported SRK alg: 0x%x.", alg);
1194 }
1195
1196 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1197 static int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template) {
1198 if (tpm2_get_srk_template(c, TPM2_ALG_ECC, ret_template) >= 0 ||
1199 tpm2_get_srk_template(c, TPM2_ALG_RSA, ret_template) >= 0)
1200 return 0;
1201
1202 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1203 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1204 }
1205
1206 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1207 * tpm2_get_or_create_srk() below. */
1208 static int tpm2_get_srk(
1209 Tpm2Context *c,
1210 const Tpm2Handle *session,
1211 TPM2B_PUBLIC **ret_public,
1212 TPM2B_NAME **ret_name,
1213 TPM2B_NAME **ret_qname,
1214 Tpm2Handle **ret_handle) {
1215
1216 return tpm2_index_to_handle(c, TPM2_SRK_HANDLE, session, ret_public, ret_name, ret_qname, ret_handle);
1217 }
1218
1219 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1220 * exists, or < 0 on error. */
1221 int tpm2_get_or_create_srk(
1222 Tpm2Context *c,
1223 const Tpm2Handle *session,
1224 TPM2B_PUBLIC **ret_public,
1225 TPM2B_NAME **ret_name,
1226 TPM2B_NAME **ret_qname,
1227 Tpm2Handle **ret_handle) {
1228
1229 int r;
1230
1231 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1232 if (r < 0)
1233 return r;
1234 if (r == 1)
1235 return 0; /* 0 → SRK already set up */
1236
1237 /* No SRK, create and persist one */
1238 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
1239 r = tpm2_get_best_srk_template(c, &template.publicArea);
1240 if (r < 0)
1241 return log_debug_errno(r, "Could not get best SRK template: %m");
1242
1243 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
1244 r = tpm2_create_primary(
1245 c,
1246 session,
1247 &template,
1248 /* sensitive= */ NULL,
1249 /* ret_public= */ NULL,
1250 &transient_handle);
1251 if (r < 0)
1252 return r;
1253
1254 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1255 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1256 * either case, all threads will get the persistent SRK below. */
1257 r = tpm2_persist_handle(c, transient_handle, session, TPM2_SRK_HANDLE, /* ret_persistent_handle= */ NULL);
1258 if (r < 0)
1259 return r;
1260
1261 /* The SRK should exist now. */
1262 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1263 if (r < 0)
1264 return r;
1265 if (r == 0)
1266 /* This should never happen. */
1267 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SRK we just persisted couldn't be found.");
1268
1269 return 1; /* > 0 → SRK newly set up */
1270 }
1271
1272 /* Utility functions for TPMS_PCR_SELECTION. */
1273
1274 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1275 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s) {
1276 assert(s);
1277 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
1278
1279 uint32_t mask = 0;
1280 for (unsigned i = 0; i < s->sizeofSelect; i++)
1281 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
1282 return mask;
1283 }
1284
1285 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1286 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
1287 assert(ret);
1288
1289 /* This is currently hardcoded at 24 PCRs, above. */
1290 if (!TPM2_PCR_MASK_VALID(mask))
1291 log_debug("PCR mask selections (%x) out of range, ignoring.",
1292 mask & ~((uint32_t)TPM2_PCRS_MASK));
1293
1294 *ret = (TPMS_PCR_SELECTION){
1295 .hash = hash_alg,
1296 .sizeofSelect = TPM2_PCRS_MAX / 8,
1297 .pcrSelect[0] = mask & 0xff,
1298 .pcrSelect[1] = (mask >> 8) & 0xff,
1299 .pcrSelect[2] = (mask >> 16) & 0xff,
1300 };
1301 }
1302
1303 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1304 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION *s, uint32_t mask) {
1305 assert(s);
1306
1307 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s), mask);
1308 }
1309
1310 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION *s, uint32_t mask, bool b) {
1311 assert(s);
1312
1313 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s), mask, b), s->hash, s);
1314 }
1315
1316 /* Add all PCR selections in the mask. */
1317 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1318 tpm2_tpms_pcr_selection_update_mask(s, mask, 1);
1319 }
1320
1321 /* Remove all PCR selections in the mask. */
1322 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1323 tpm2_tpms_pcr_selection_update_mask(s, mask, 0);
1324 }
1325
1326 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1327 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1328 assert(a);
1329 assert(b);
1330 assert(a->hash == b->hash);
1331
1332 tpm2_tpms_pcr_selection_add_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1333 }
1334
1335 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1336 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1337 assert(a);
1338 assert(b);
1339 assert(a->hash == b->hash);
1340
1341 tpm2_tpms_pcr_selection_sub_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1342 }
1343
1344 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1345 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
1346 if (a == b)
1347 return;
1348
1349 tpm2_tpms_pcr_selection_add(a, b);
1350 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
1351 }
1352
1353 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1354 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1355 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1356 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1357 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1358
1359 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1360 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1361
1362 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1363 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1364 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1365
1366 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
1367 assert(s);
1368
1369 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
1370
1371 _cleanup_free_ char *mask = tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s));
1372 if (!mask)
1373 return NULL;
1374
1375 return strjoin(algstr, "(", mask, ")");
1376 }
1377
1378 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
1379 assert(s);
1380
1381 return popcount(tpm2_tpms_pcr_selection_to_mask(s));
1382 }
1383
1384 /* Utility functions for TPML_PCR_SELECTION. */
1385
1386 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1387 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
1388 assert(l);
1389 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1390 assert(index < l->count);
1391
1392 size_t s = l->count - (index + 1);
1393 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
1394 l->count--;
1395 }
1396
1397 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1398 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1399 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1400 static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1401 TPML_PCR_SELECTION *l,
1402 TPMI_ALG_HASH hash_alg) {
1403
1404 assert(l);
1405 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1406
1407 TPMS_PCR_SELECTION *selection = NULL;
1408 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1409 if (s->hash == hash_alg) {
1410 selection = s;
1411 break;
1412 }
1413
1414 if (!selection)
1415 return NULL;
1416
1417 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1418 for (uint32_t i = l->count - 1; i > 0; i--) {
1419 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
1420
1421 if (selection == s)
1422 break;
1423
1424 if (s->hash == hash_alg) {
1425 tpm2_tpms_pcr_selection_move(selection, s);
1426 tpm2_tpml_pcr_selection_remove_index(l, i);
1427 }
1428 }
1429
1430 return selection;
1431 }
1432
1433 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1434 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
1435 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1436 for (uint32_t i = 0; i < l->count; i++)
1437 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1438 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, l->pcrSelections[i].hash);
1439 }
1440
1441 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1442 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg) {
1443 assert(l);
1444
1445 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1446 * are multiple entries with the requested hash alg. */
1447 TPML_PCR_SELECTION lcopy = *l;
1448
1449 TPMS_PCR_SELECTION *s;
1450 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
1451 if (!s)
1452 return 0;
1453
1454 return tpm2_tpms_pcr_selection_to_mask(s);
1455 }
1456
1457 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1458 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
1459 assert(ret);
1460
1461 TPMS_PCR_SELECTION s;
1462 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
1463
1464 *ret = (TPML_PCR_SELECTION){
1465 .count = 1,
1466 .pcrSelections[0] = s,
1467 };
1468 }
1469
1470 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1471 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1472 * entries with the same hash alg. */
1473 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1474 assert(l);
1475 assert(s);
1476
1477 if (tpm2_tpms_pcr_selection_is_empty(s))
1478 return;
1479
1480 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1481 if (selection) {
1482 tpm2_tpms_pcr_selection_add(selection, s);
1483 return;
1484 }
1485
1486 /* It's already broken if the count is higher than the array has size for. */
1487 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1488
1489 /* If full, the cleanup should result in at least one available entry. */
1490 if (l->count == ELEMENTSOF(l->pcrSelections))
1491 tpm2_tpml_pcr_selection_cleanup(l);
1492
1493 assert(l->count < ELEMENTSOF(l->pcrSelections));
1494 l->pcrSelections[l->count++] = *s;
1495 }
1496
1497 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1498 * will combine all entries for 's->hash' in 'l'. */
1499 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1500 assert(l);
1501 assert(s);
1502
1503 if (tpm2_tpms_pcr_selection_is_empty(s))
1504 return;
1505
1506 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1507 if (selection)
1508 tpm2_tpms_pcr_selection_sub(selection, s);
1509 }
1510
1511 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1512 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1513 assert(l);
1514
1515 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l, hash), mask);
1516 }
1517
1518 /* Add the PCR selections in the mask, with the provided hash. */
1519 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1520 TPMS_PCR_SELECTION tpms;
1521
1522 assert(l);
1523
1524 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1525 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l, &tpms);
1526 }
1527
1528 /* Remove the PCR selections in the mask, with the provided hash. */
1529 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1530 TPMS_PCR_SELECTION tpms;
1531
1532 assert(l);
1533
1534 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1535 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l, &tpms);
1536 }
1537
1538 /* Add all PCR selections in 'b' to 'a'. */
1539 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1540 assert(a);
1541 assert(b);
1542
1543 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1544 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
1545 }
1546
1547 /* Remove all PCR selections in 'b' from 'a'. */
1548 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1549 assert(a);
1550 assert(b);
1551
1552 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1553 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
1554 }
1555
1556 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
1557 assert(l);
1558
1559 _cleanup_free_ char *banks = NULL;
1560 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1561 if (tpm2_tpms_pcr_selection_is_empty(s))
1562 continue;
1563
1564 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
1565 if (!str || !strextend_with_separator(&banks, ",", str))
1566 return NULL;
1567 }
1568
1569 return strjoin("[", strempty(banks), "]");
1570 }
1571
1572 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
1573 assert(l);
1574 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1575
1576 size_t weight = 0;
1577 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1578 size_t w = tpm2_tpms_pcr_selection_weight(s);
1579 assert(weight <= SIZE_MAX - w);
1580 weight += w;
1581 }
1582
1583 return weight;
1584 }
1585
1586 bool tpm2_pcr_value_valid(const Tpm2PCRValue *pcr_value) {
1587 int r;
1588
1589 if (!pcr_value)
1590 return false;
1591
1592 if (!TPM2_PCR_INDEX_VALID(pcr_value->index)) {
1593 log_debug("PCR index %u invalid.", pcr_value->index);
1594 return false;
1595 }
1596
1597 /* If it contains a value, the value size must match the hash size. */
1598 if (pcr_value->value.size > 0) {
1599 r = tpm2_hash_alg_to_size(pcr_value->hash);
1600 if (r < 0)
1601 return false;
1602
1603 if (pcr_value->value.size != (size_t) r) {
1604 log_debug("PCR hash 0x%" PRIx16 " expected size %d does not match actual size %" PRIu16 ".",
1605 pcr_value->hash, r, pcr_value->value.size);
1606 return false;
1607 }
1608 }
1609
1610 return true;
1611 }
1612
1613 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1614 *
1615 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1616 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1617 *
1618 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1619 */
1620 bool tpm2_pcr_values_valid(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1621 if (!pcr_values && n_pcr_values > 0)
1622 return false;
1623
1624 const Tpm2PCRValue *previous = NULL;
1625 FOREACH_ARRAY(current, pcr_values, n_pcr_values) {
1626 if (!tpm2_pcr_value_valid(current))
1627 return false;
1628
1629 if (!previous) {
1630 previous = current;
1631 continue;
1632 }
1633
1634 /* Hashes must be sorted in ascending order */
1635 if (current->hash < previous->hash) {
1636 log_debug("PCR values not in ascending order, hash %" PRIu16 " is after %" PRIu16 ".",
1637 current->hash, previous->hash);
1638 return false;
1639 }
1640
1641 if (current->hash == previous->hash) {
1642 /* Indexes (for the same hash) must be sorted in ascending order */
1643 if (current->index < previous->index) {
1644 log_debug("PCR values not in ascending order, hash %" PRIu16 " index %u is after %u.",
1645 current->hash, current->index, previous->index);
1646 return false;
1647 }
1648
1649 /* Indexes (for the same hash) must not be duplicates */
1650 if (current->index == previous->index) {
1651 log_debug("PCR values contain duplicates for hash %" PRIu16 " index %u.",
1652 current->hash, previous->index);
1653 return false;
1654 }
1655 }
1656 }
1657
1658 return true;
1659 }
1660
1661 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1662 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1663 assert(pcr_values || n_pcr_values == 0);
1664
1665 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1666 if (v->value.size > 0)
1667 return true;
1668
1669 return false;
1670 }
1671
1672 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1673 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1674 assert(pcr_values || n_pcr_values == 0);
1675
1676 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1677 if (v->value.size == 0)
1678 return false;
1679
1680 return true;
1681 }
1682
1683 static int cmp_pcr_values(const Tpm2PCRValue *a, const Tpm2PCRValue *b) {
1684 assert(a);
1685 assert(b);
1686
1687 return CMP(a->hash, b->hash) ?: CMP(a->index, b->index);
1688 }
1689
1690 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1691 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1692 void tpm2_sort_pcr_values(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1693 typesafe_qsort(pcr_values, n_pcr_values, cmp_pcr_values);
1694 }
1695
1696 int tpm2_pcr_values_from_mask(uint32_t mask, TPMI_ALG_HASH hash, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1697 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1698 size_t n_pcr_values = 0;
1699
1700 assert(ret_pcr_values);
1701 assert(ret_n_pcr_values);
1702
1703 FOREACH_PCR_IN_MASK(index, mask)
1704 if (!GREEDY_REALLOC_APPEND(
1705 pcr_values,
1706 n_pcr_values,
1707 &TPM2_PCR_VALUE_MAKE(index, hash, {}),
1708 1))
1709 return log_oom_debug();
1710
1711 *ret_pcr_values = TAKE_PTR(pcr_values);
1712 *ret_n_pcr_values = n_pcr_values;
1713
1714 return 0;
1715 }
1716
1717 int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPMI_ALG_HASH hash, uint32_t *ret_mask) {
1718 uint32_t mask = 0;
1719
1720 assert(pcr_values || n_pcr_values == 0);
1721 assert(ret_mask);
1722
1723 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1724 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PCR values.");
1725
1726 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1727 if (v->hash == hash)
1728 SET_BIT(mask, v->index);
1729
1730 *ret_mask = mask;
1731
1732 return 0;
1733 }
1734
1735 int tpm2_tpml_pcr_selection_from_pcr_values(
1736 const Tpm2PCRValue *pcr_values,
1737 size_t n_pcr_values,
1738 TPML_PCR_SELECTION *ret_selection,
1739 TPM2B_DIGEST **ret_values,
1740 size_t *ret_n_values) {
1741
1742 TPML_PCR_SELECTION selection = {};
1743 _cleanup_free_ TPM2B_DIGEST *values = NULL;
1744 size_t n_values = 0;
1745
1746 assert(pcr_values || n_pcr_values == 0);
1747
1748 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1749 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "PCR values are not valid.");
1750
1751 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1752 tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
1753
1754 if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
1755 return log_oom_debug();
1756 }
1757
1758 if (ret_selection)
1759 *ret_selection = selection;
1760 if (ret_values)
1761 *ret_values = TAKE_PTR(values);
1762 if (ret_n_values)
1763 *ret_n_values = n_values;
1764
1765 return 0;
1766 }
1767
1768 /* Count the number of different hash algorithms for all the entries. */
1769 int tpm2_pcr_values_hash_count(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, size_t *ret_count) {
1770 TPML_PCR_SELECTION selection;
1771 int r;
1772
1773 assert(pcr_values);
1774 assert(ret_count);
1775
1776 r = tpm2_tpml_pcr_selection_from_pcr_values(
1777 pcr_values,
1778 n_pcr_values,
1779 &selection,
1780 /* ret_values= */ NULL,
1781 /* ret_n_values= */ NULL);
1782 if (r < 0)
1783 return r;
1784
1785 *ret_count = selection.count;
1786
1787 return 0;
1788 }
1789
1790 /* Parse a string argument into a Tpm2PCRValue object.
1791 *
1792 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1793 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1794 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1795 int tpm2_pcr_value_from_string(const char *arg, Tpm2PCRValue *ret_pcr_value) {
1796 Tpm2PCRValue pcr_value = {};
1797 const char *p = arg;
1798 int r;
1799
1800 assert(arg);
1801 assert(ret_pcr_value);
1802
1803 _cleanup_free_ char *index = NULL;
1804 r = extract_first_word(&p, &index, ":", /* flags= */ 0);
1805 if (r < 1)
1806 return log_debug_errno(r, "Could not parse pcr value '%s': %m", p);
1807
1808 r = tpm2_pcr_index_from_string(index);
1809 if (r < 0)
1810 return log_debug_errno(r, "Invalid pcr index '%s': %m", index);
1811 pcr_value.index = (unsigned) r;
1812
1813 if (!isempty(p)) {
1814 _cleanup_free_ char *hash = NULL;
1815 r = extract_first_word(&p, &hash, "=", /* flags= */ 0);
1816 if (r < 1)
1817 return log_debug_errno(r, "Could not parse pcr hash algorithm '%s': %m", p);
1818
1819 r = tpm2_hash_alg_from_string(hash);
1820 if (r < 0)
1821 return log_debug_errno(r, "Invalid pcr hash algorithm '%s': %m", hash);
1822 pcr_value.hash = (TPMI_ALG_HASH) r;
1823
1824 if (!isempty(p)) {
1825 /* Remove leading 0x if present */
1826 p = startswith_no_case(p, "0x") ?: p;
1827
1828 _cleanup_free_ void *buf = NULL;
1829 size_t buf_size = 0;
1830 r = unhexmem(p, SIZE_MAX, &buf, &buf_size);
1831 if (r < 0)
1832 return log_debug_errno(r, "Invalid pcr hash value '%s': %m", p);
1833
1834 r = TPM2B_DIGEST_CHECK_SIZE(buf_size);
1835 if (r < 0)
1836 return log_debug_errno(r, "PCR hash value size %zu too large.", buf_size);
1837
1838 pcr_value.value = TPM2B_DIGEST_MAKE(buf, buf_size);
1839 }
1840 }
1841
1842 *ret_pcr_value = pcr_value;
1843
1844 return 0;
1845 }
1846
1847 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1848 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1849 * string. This does not check for validity. */
1850 char *tpm2_pcr_value_to_string(const Tpm2PCRValue *pcr_value) {
1851 _cleanup_free_ char *index = NULL, *value = NULL;
1852
1853 if (asprintf(&index, "%u", pcr_value->index) < 0)
1854 return NULL;
1855
1856 const char *hash = pcr_value->hash > 0 ? tpm2_hash_alg_to_string(pcr_value->hash) : NULL;
1857
1858 if (hash && pcr_value->value.size > 0) {
1859 value = hexmem(pcr_value->value.buffer, pcr_value->value.size);
1860 if (!value)
1861 return NULL;
1862 }
1863
1864 return strjoin(index, hash ? ":" : "", strempty(hash), value ? "=" : "", strempty(value));
1865 }
1866
1867 /* Parse a string argument into an array of Tpm2PCRValue objects.
1868 *
1869 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1870 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1871 int tpm2_pcr_values_from_string(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1872 const char *p = arg;
1873 int r;
1874
1875 assert(arg);
1876 assert(ret_pcr_values);
1877 assert(ret_n_pcr_values);
1878
1879 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1880 size_t n_pcr_values = 0;
1881
1882 for (;;) {
1883 _cleanup_free_ char *pcr_arg = NULL;
1884 r = extract_first_word(&p, &pcr_arg, ",+", /* flags= */ 0);
1885 if (r < 0)
1886 return log_debug_errno(r, "Could not parse pcr values '%s': %m", p);
1887 if (r == 0)
1888 break;
1889
1890 Tpm2PCRValue pcr_value;
1891 r = tpm2_pcr_value_from_string(pcr_arg, &pcr_value);
1892 if (r < 0)
1893 return r;
1894
1895 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
1896 return log_oom_debug();
1897 }
1898
1899 *ret_pcr_values = TAKE_PTR(pcr_values);
1900 *ret_n_pcr_values = n_pcr_values;
1901
1902 return 0;
1903 }
1904
1905 /* Return a string representing the array of PCR values. The format is as described in
1906 * tpm2_pcr_values_from_string(). This does not check for validity. */
1907 char *tpm2_pcr_values_to_string(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1908 _cleanup_free_ char *s = NULL;
1909
1910 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1911 _cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(v);
1912 if (!pcrstr || !strextend_with_separator(&s, "+", pcrstr))
1913 return NULL;
1914 }
1915
1916 return s ? TAKE_PTR(s) : strdup("");
1917 }
1918
1919 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
1920 if (!DEBUG_LOGGING || !l)
1921 return;
1922
1923 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
1924 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
1925 }
1926
1927 void tpm2_log_debug_pcr_value(const Tpm2PCRValue *pcr_value, const char *msg) {
1928 if (!DEBUG_LOGGING || !pcr_value)
1929 return;
1930
1931 _cleanup_free_ char *s = tpm2_pcr_value_to_string(pcr_value);
1932 log_debug("%s: %s", msg ?: "PCR value", strna(s));
1933 }
1934
1935 void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
1936 if (!DEBUG_LOGGING || !buffer || size == 0)
1937 return;
1938
1939 _cleanup_free_ char *h = hexmem(buffer, size);
1940 log_debug("%s: %s", msg ?: "Buffer", strna(h));
1941 }
1942
1943 void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
1944 if (digest)
1945 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
1946 }
1947
1948 void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
1949 if (name)
1950 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
1951 }
1952
1953 static int tpm2_get_policy_digest(
1954 Tpm2Context *c,
1955 const Tpm2Handle *session,
1956 TPM2B_DIGEST **ret_policy_digest) {
1957
1958 TSS2_RC rc;
1959
1960 if (!DEBUG_LOGGING && !ret_policy_digest)
1961 return 0;
1962
1963 assert(c);
1964 assert(session);
1965
1966 log_debug("Acquiring policy digest.");
1967
1968 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1969 rc = sym_Esys_PolicyGetDigest(
1970 c->esys_context,
1971 session->esys_handle,
1972 ESYS_TR_NONE,
1973 ESYS_TR_NONE,
1974 ESYS_TR_NONE,
1975 &policy_digest);
1976 if (rc != TSS2_RC_SUCCESS)
1977 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1978 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1979
1980 tpm2_log_debug_digest(policy_digest, "Session policy digest");
1981
1982 if (ret_policy_digest)
1983 *ret_policy_digest = TAKE_PTR(policy_digest);
1984
1985 return 0;
1986 }
1987
1988 int tpm2_create_primary(
1989 Tpm2Context *c,
1990 const Tpm2Handle *session,
1991 const TPM2B_PUBLIC *template,
1992 const TPM2B_SENSITIVE_CREATE *sensitive,
1993 TPM2B_PUBLIC **ret_public,
1994 Tpm2Handle **ret_handle) {
1995
1996 usec_t ts;
1997 TSS2_RC rc;
1998 int r;
1999
2000 assert(c);
2001 assert(template);
2002
2003 log_debug("Creating primary key on TPM.");
2004
2005 ts = now(CLOCK_MONOTONIC);
2006
2007 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2008 r = tpm2_handle_new(c, &handle);
2009 if (r < 0)
2010 return r;
2011
2012 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2013 rc = sym_Esys_CreatePrimary(
2014 c->esys_context,
2015 ESYS_TR_RH_OWNER,
2016 session ? session->esys_handle : ESYS_TR_PASSWORD,
2017 ESYS_TR_NONE,
2018 ESYS_TR_NONE,
2019 sensitive ? sensitive : &(TPM2B_SENSITIVE_CREATE) {},
2020 template,
2021 /* outsideInfo= */ NULL,
2022 &(TPML_PCR_SELECTION) {},
2023 &handle->esys_handle,
2024 &public,
2025 /* creationData= */ NULL,
2026 /* creationHash= */ NULL,
2027 /* creationTicket= */ NULL);
2028 if (rc != TSS2_RC_SUCCESS)
2029 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2030 "Failed to generate primary key in TPM: %s",
2031 sym_Tss2_RC_Decode(rc));
2032
2033 log_debug("Successfully created primary key on TPM in %s.",
2034 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2035
2036 if (ret_public)
2037 *ret_public = TAKE_PTR(public);
2038 if (ret_handle)
2039 *ret_handle = TAKE_PTR(handle);
2040
2041 return 0;
2042 }
2043
2044 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2045 * instead use tpm2_create_primary(). */
2046 int tpm2_create(Tpm2Context *c,
2047 const Tpm2Handle *parent,
2048 const Tpm2Handle *session,
2049 const TPMT_PUBLIC *template,
2050 const TPMS_SENSITIVE_CREATE *sensitive,
2051 TPM2B_PUBLIC **ret_public,
2052 TPM2B_PRIVATE **ret_private) {
2053
2054 usec_t ts;
2055 TSS2_RC rc;
2056
2057 assert(c);
2058 assert(parent);
2059 assert(template);
2060
2061 log_debug("Creating object on TPM.");
2062
2063 ts = now(CLOCK_MONOTONIC);
2064
2065 TPM2B_PUBLIC tpm2b_public = {
2066 .size = sizeof(*template) - sizeof(template->unique),
2067 .publicArea = *template,
2068 };
2069
2070 /* Zero the unique area. */
2071 zero(tpm2b_public.publicArea.unique);
2072
2073 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2074 if (sensitive)
2075 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2076 .size = sizeof(*sensitive),
2077 .sensitive = *sensitive,
2078 };
2079 else
2080 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2081
2082 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2083 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2084 rc = sym_Esys_Create(
2085 c->esys_context,
2086 parent->esys_handle,
2087 session ? session->esys_handle : ESYS_TR_PASSWORD,
2088 ESYS_TR_NONE,
2089 ESYS_TR_NONE,
2090 &tpm2b_sensitive,
2091 &tpm2b_public,
2092 /* outsideInfo= */ NULL,
2093 &(TPML_PCR_SELECTION) {},
2094 &private,
2095 &public,
2096 /* creationData= */ NULL,
2097 /* creationHash= */ NULL,
2098 /* creationTicket= */ NULL);
2099 if (rc != TSS2_RC_SUCCESS)
2100 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2101 "Failed to generate object in TPM: %s",
2102 sym_Tss2_RC_Decode(rc));
2103
2104 log_debug("Successfully created object on TPM in %s.",
2105 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2106
2107 if (ret_public)
2108 *ret_public = TAKE_PTR(public);
2109 if (ret_private)
2110 *ret_private = TAKE_PTR(private);
2111
2112 return 0;
2113 }
2114
2115 static int tpm2_load(
2116 Tpm2Context *c,
2117 const Tpm2Handle *parent,
2118 const Tpm2Handle *session,
2119 const TPM2B_PUBLIC *public,
2120 const TPM2B_PRIVATE *private,
2121 Tpm2Handle **ret_handle) {
2122
2123 TSS2_RC rc;
2124 int r;
2125
2126 assert(c);
2127 assert(public);
2128 assert(private);
2129 assert(ret_handle);
2130
2131 log_debug("Loading object into TPM.");
2132
2133 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2134 r = tpm2_handle_new(c, &handle);
2135 if (r < 0)
2136 return r;
2137
2138 rc = sym_Esys_Load(
2139 c->esys_context,
2140 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
2141 session ? session->esys_handle : ESYS_TR_PASSWORD,
2142 ESYS_TR_NONE,
2143 ESYS_TR_NONE,
2144 private,
2145 public,
2146 &handle->esys_handle);
2147 if (rc == TPM2_RC_LOCKOUT)
2148 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK),
2149 "TPM2 device is in dictionary attack lockout mode.");
2150 if (rc != TSS2_RC_SUCCESS)
2151 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2152 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc));
2153
2154 *ret_handle = TAKE_PTR(handle);
2155
2156 return 0;
2157 }
2158
2159 static int tpm2_load_external(
2160 Tpm2Context *c,
2161 const Tpm2Handle *session,
2162 const TPM2B_PUBLIC *public,
2163 const TPM2B_SENSITIVE *private,
2164 Tpm2Handle **ret_handle) {
2165
2166 TSS2_RC rc;
2167 int r;
2168
2169 assert(c);
2170 assert(ret_handle);
2171
2172 log_debug("Loading external key into TPM.");
2173
2174 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2175 r = tpm2_handle_new(c, &handle);
2176 if (r < 0)
2177 return r;
2178
2179 rc = sym_Esys_LoadExternal(
2180 c->esys_context,
2181 session ? session->esys_handle : ESYS_TR_NONE,
2182 ESYS_TR_NONE,
2183 ESYS_TR_NONE,
2184 private,
2185 public,
2186 #if HAVE_TSS2_ESYS3
2187 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2188 * hierarchy, older versions need TPM2_RH_* instead. */
2189 ESYS_TR_RH_OWNER,
2190 #else
2191 TPM2_RH_OWNER,
2192 #endif
2193 &handle->esys_handle);
2194 if (rc != TSS2_RC_SUCCESS)
2195 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2196 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
2197
2198 *ret_handle = TAKE_PTR(handle);
2199
2200 return 0;
2201 }
2202
2203 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2204 * use tpm2_create_loaded(). */
2205 static int _tpm2_create_loaded(
2206 Tpm2Context *c,
2207 const Tpm2Handle *parent,
2208 const Tpm2Handle *session,
2209 const TPMT_PUBLIC *template,
2210 const TPMS_SENSITIVE_CREATE *sensitive,
2211 TPM2B_PUBLIC **ret_public,
2212 TPM2B_PRIVATE **ret_private,
2213 Tpm2Handle **ret_handle) {
2214
2215 usec_t ts;
2216 TSS2_RC rc;
2217 int r;
2218
2219 assert(c);
2220 assert(parent);
2221 assert(template);
2222
2223 log_debug("Creating loaded object on TPM.");
2224
2225 ts = now(CLOCK_MONOTONIC);
2226
2227 /* Copy the input template and zero the unique area. */
2228 TPMT_PUBLIC template_copy = *template;
2229 zero(template_copy.unique);
2230
2231 TPM2B_TEMPLATE tpm2b_template;
2232 size_t size = 0;
2233 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2234 &template_copy,
2235 tpm2b_template.buffer,
2236 sizeof(tpm2b_template.buffer),
2237 &size);
2238 if (rc != TSS2_RC_SUCCESS)
2239 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2240 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc));
2241 assert(size <= UINT16_MAX);
2242 tpm2b_template.size = size;
2243
2244 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2245 if (sensitive)
2246 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2247 .size = sizeof(*sensitive),
2248 .sensitive = *sensitive,
2249 };
2250 else
2251 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2252
2253 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2254 r = tpm2_handle_new(c, &handle);
2255 if (r < 0)
2256 return r;
2257
2258 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2259 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2260 rc = sym_Esys_CreateLoaded(
2261 c->esys_context,
2262 parent->esys_handle,
2263 session ? session->esys_handle : ESYS_TR_PASSWORD,
2264 ESYS_TR_NONE,
2265 ESYS_TR_NONE,
2266 &tpm2b_sensitive,
2267 &tpm2b_template,
2268 &handle->esys_handle,
2269 &private,
2270 &public);
2271 if (rc != TSS2_RC_SUCCESS)
2272 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2273 "Failed to generate loaded object in TPM: %s",
2274 sym_Tss2_RC_Decode(rc));
2275
2276 log_debug("Successfully created loaded object on TPM in %s.",
2277 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2278
2279 if (ret_public)
2280 *ret_public = TAKE_PTR(public);
2281 if (ret_private)
2282 *ret_private = TAKE_PTR(private);
2283 if (ret_handle)
2284 *ret_handle = TAKE_PTR(handle);
2285
2286 return 0;
2287 }
2288
2289 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2290 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2291 * tpm2_create_primary(). */
2292 int tpm2_create_loaded(
2293 Tpm2Context *c,
2294 const Tpm2Handle *parent,
2295 const Tpm2Handle *session,
2296 const TPMT_PUBLIC *template,
2297 const TPMS_SENSITIVE_CREATE *sensitive,
2298 TPM2B_PUBLIC **ret_public,
2299 TPM2B_PRIVATE **ret_private,
2300 Tpm2Handle **ret_handle) {
2301
2302 int r;
2303
2304 if (tpm2_supports_command(c, TPM2_CC_CreateLoaded))
2305 return _tpm2_create_loaded(c, parent, session, template, sensitive, ret_public, ret_private, ret_handle);
2306
2307 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2308 * create and load manually. */
2309 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2310 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2311 r = tpm2_create(c, parent, session, template, sensitive, &public, &private);
2312 if (r < 0)
2313 return r;
2314
2315 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2316 r = tpm2_load(c, parent, session, public, private, &handle);
2317 if (r < 0)
2318 return r;
2319
2320 if (ret_public)
2321 *ret_public = TAKE_PTR(public);
2322 if (ret_private)
2323 *ret_private = TAKE_PTR(private);
2324 if (ret_handle)
2325 *ret_handle = TAKE_PTR(handle);
2326
2327 return 0;
2328 }
2329
2330 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2331 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2332 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2333 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2334 * values. */
2335 int tpm2_pcr_read(
2336 Tpm2Context *c,
2337 const TPML_PCR_SELECTION *pcr_selection,
2338 Tpm2PCRValue **ret_pcr_values,
2339 size_t *ret_n_pcr_values) {
2340
2341 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2342 size_t n_pcr_values = 0;
2343 TSS2_RC rc;
2344
2345 assert(c);
2346 assert(pcr_selection);
2347 assert(ret_pcr_values);
2348 assert(ret_n_pcr_values);
2349
2350 TPML_PCR_SELECTION remaining = *pcr_selection;
2351 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
2352 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
2353 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
2354
2355 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
2356
2357 /* Unfortunately, PCR_Read will not return more than 8 values. */
2358 rc = sym_Esys_PCR_Read(
2359 c->esys_context,
2360 ESYS_TR_NONE,
2361 ESYS_TR_NONE,
2362 ESYS_TR_NONE,
2363 &remaining,
2364 NULL,
2365 &current_read,
2366 &current_values);
2367 if (rc != TSS2_RC_SUCCESS)
2368 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2369 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
2370
2371 tpm2_log_debug_tpml_pcr_selection(current_read, "Read PCR selection");
2372
2373 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
2374 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2375 break;
2376 }
2377
2378 unsigned i = 0;
2379 FOREACH_PCR_IN_TPML_PCR_SELECTION(index, tpms, current_read) {
2380 assert(i < current_values->count);
2381 Tpm2PCRValue pcr_value = {
2382 .index = index,
2383 .hash = tpms->hash,
2384 .value = current_values->digests[i++],
2385 };
2386
2387 tpm2_log_debug_pcr_value(&pcr_value, /* msg= */ NULL);
2388
2389 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
2390 return log_oom_debug();
2391 }
2392 assert(i == current_values->count);
2393
2394 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
2395 }
2396
2397 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
2398
2399 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
2400 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PCR values read from TPM are not valid.");
2401
2402 *ret_pcr_values = TAKE_PTR(pcr_values);
2403 *ret_n_pcr_values = n_pcr_values;
2404
2405 return 0;
2406 }
2407
2408 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2409 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2410 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2411 * appropriate entries, this returns an error. This does not check the array for validity. */
2412 int tpm2_pcr_read_missing_values(Tpm2Context *c, Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
2413 TPMI_ALG_HASH pcr_bank = 0;
2414 int r;
2415
2416 assert(c);
2417 assert(pcr_values || n_pcr_values == 0);
2418
2419 if (n_pcr_values > 0) {
2420 size_t hash_count;
2421 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
2422 if (r < 0)
2423 return log_debug_errno(r, "Could not get hash count from pcr values: %m");
2424
2425 if (hash_count == 1 && pcr_values[0].hash == 0) {
2426 uint32_t mask;
2427 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, 0, &mask);
2428 if (r < 0)
2429 return r;
2430
2431 r = tpm2_get_best_pcr_bank(c, mask, &pcr_bank);
2432 if (r < 0)
2433 return r;
2434 }
2435 }
2436
2437 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
2438 if (v->hash == 0)
2439 v->hash = pcr_bank;
2440
2441 if (v->value.size > 0)
2442 continue;
2443
2444 TPML_PCR_SELECTION selection;
2445 r = tpm2_tpml_pcr_selection_from_pcr_values(v, 1, &selection, NULL, NULL);
2446 if (r < 0)
2447 return r;
2448
2449 _cleanup_free_ Tpm2PCRValue *read_values = NULL;
2450 size_t n_read_values;
2451 r = tpm2_pcr_read(c, &selection, &read_values, &n_read_values);
2452 if (r < 0)
2453 return r;
2454
2455 if (n_read_values == 0)
2456 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2457 "Could not read PCR hash 0x%" PRIu16 " index %u",
2458 v->hash, v->index);
2459
2460 assert(n_read_values == 1);
2461 assert(read_values[0].hash == v->hash);
2462 assert(read_values[0].index == v->index);
2463
2464 v->value = read_values[0].value;
2465 }
2466
2467 return 0;
2468 }
2469
2470 static int tpm2_pcr_mask_good(
2471 Tpm2Context *c,
2472 TPMI_ALG_HASH bank,
2473 uint32_t mask) {
2474
2475 TPML_PCR_SELECTION selection;
2476 int r;
2477
2478 assert(c);
2479
2480 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2481 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2482 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2483
2484 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
2485
2486 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2487 size_t n_pcr_values;
2488 r = tpm2_pcr_read(c, &selection, &pcr_values, &n_pcr_values);
2489 if (r < 0)
2490 return r;
2491
2492 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2493 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
2494 if (!memeqbyte(0x00, v->value.buffer, v->value.size) &&
2495 !memeqbyte(0xFF, v->value.buffer, v->value.size))
2496 return true;
2497
2498 return false;
2499 }
2500
2501 static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
2502
2503 assert(selection);
2504
2505 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2506 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2507 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
2508 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2509 strna(tpm2_hash_alg_to_string(selection->hash)));
2510 return false;
2511 }
2512
2513 assert_cc(TPM2_PCRS_MAX % 8 == 0);
2514
2515 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2516 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2517 bool valid = true;
2518 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
2519 if (selection->pcrSelect[j] != 0xFF) {
2520 valid = false;
2521 break;
2522 }
2523
2524 if (!valid)
2525 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2526 strna(tpm2_hash_alg_to_string(selection->hash)));
2527
2528 return valid;
2529 }
2530
2531 int tpm2_get_best_pcr_bank(
2532 Tpm2Context *c,
2533 uint32_t pcr_mask,
2534 TPMI_ALG_HASH *ret) {
2535
2536 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
2537 int r;
2538
2539 assert(c);
2540 assert(ret);
2541
2542 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2543 TPMI_ALG_HASH hash = selection->hash;
2544 int good;
2545
2546 /* For now we are only interested in the SHA1 and SHA256 banks */
2547 if (!IN_SET(hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
2548 continue;
2549
2550 r = tpm2_bank_has24(selection);
2551 if (r < 0)
2552 return r;
2553 if (!r)
2554 continue;
2555
2556 good = tpm2_pcr_mask_good(c, hash, pcr_mask);
2557 if (good < 0)
2558 return good;
2559
2560 if (hash == TPM2_ALG_SHA256) {
2561 supported_hash = TPM2_ALG_SHA256;
2562 if (good) {
2563 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2564 hash_with_valid_pcr = TPM2_ALG_SHA256;
2565 break;
2566 }
2567 } else {
2568 assert(hash == TPM2_ALG_SHA1);
2569
2570 if (supported_hash == 0)
2571 supported_hash = TPM2_ALG_SHA1;
2572
2573 if (good && hash_with_valid_pcr == 0)
2574 hash_with_valid_pcr = TPM2_ALG_SHA1;
2575 }
2576 }
2577
2578 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2579 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2580 * SHA1.
2581 *
2582 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2583 * not initialized. */
2584
2585 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
2586 assert(supported_hash == TPM2_ALG_SHA256);
2587 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2588 *ret = TPM2_ALG_SHA256;
2589 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
2590 if (supported_hash == TPM2_ALG_SHA256)
2591 log_notice("TPM2 device supports both SHA1 and SHA256 PCR banks, but only SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
2592 else {
2593 assert(supported_hash == TPM2_ALG_SHA1);
2594 log_notice("TPM2 device lacks support for SHA256 PCR bank, but SHA1 bank is supported and SHA1 PCRs are valid, falling back to SHA1 bank. This reduces the security level substantially.");
2595 }
2596
2597 *ret = TPM2_ALG_SHA1;
2598 } else if (supported_hash == TPM2_ALG_SHA256) {
2599 log_notice("TPM2 device supports SHA256 PCR bank but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA256 bank. PCR policy effectively unenforced!");
2600 *ret = TPM2_ALG_SHA256;
2601 } else if (supported_hash == TPM2_ALG_SHA1) {
2602 log_notice("TPM2 device lacks support for SHA256 bank, but SHA1 bank is supported, but none of the selected PCRs are valid! Firmware apparently did not initialize any of the selected PCRs. Proceeding anyway with SHA1 bank. PCR policy effectively unenforced!");
2603 *ret = TPM2_ALG_SHA1;
2604 } else
2605 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2606 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2607
2608 return 0;
2609 }
2610
2611 int tpm2_get_good_pcr_banks(
2612 Tpm2Context *c,
2613 uint32_t pcr_mask,
2614 TPMI_ALG_HASH **ret) {
2615
2616 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
2617 size_t n_good_banks = 0, n_fallback_banks = 0;
2618 int r;
2619
2620 assert(c);
2621 assert(ret);
2622
2623 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2624 TPMI_ALG_HASH hash = selection->hash;
2625
2626 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2627 r = tpm2_bank_has24(selection);
2628 if (r < 0)
2629 return r;
2630 if (!r)
2631 continue;
2632
2633 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2634 r = tpm2_pcr_mask_good(c, hash, pcr_mask);
2635 if (r < 0)
2636 return r;
2637
2638 if (n_good_banks + n_fallback_banks >= INT_MAX)
2639 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
2640
2641 if (r) {
2642 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
2643 return log_oom_debug();
2644
2645 good_banks[n_good_banks++] = hash;
2646 } else {
2647 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
2648 return log_oom_debug();
2649
2650 fallback_banks[n_fallback_banks++] = hash;
2651 }
2652 }
2653
2654 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2655 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2656 if (n_good_banks > 0) {
2657 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
2658 *ret = TAKE_PTR(good_banks);
2659 return (int) n_good_banks;
2660 }
2661 if (n_fallback_banks > 0) {
2662 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
2663 *ret = TAKE_PTR(fallback_banks);
2664 return (int) n_fallback_banks;
2665 }
2666
2667 /* No suitable banks found. */
2668 *ret = NULL;
2669 return 0;
2670 }
2671
2672 int tpm2_get_good_pcr_banks_strv(
2673 Tpm2Context *c,
2674 uint32_t pcr_mask,
2675 char ***ret) {
2676
2677 #if HAVE_OPENSSL
2678 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
2679 _cleanup_strv_free_ char **l = NULL;
2680 int n_algs;
2681
2682 assert(c);
2683 assert(ret);
2684
2685 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
2686 if (n_algs < 0)
2687 return n_algs;
2688
2689 FOREACH_ARRAY(a, algs, n_algs) {
2690 _cleanup_free_ char *n = NULL;
2691 const EVP_MD *implementation;
2692 const char *salg;
2693
2694 salg = tpm2_hash_alg_to_string(*a);
2695 if (!salg)
2696 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
2697
2698 implementation = EVP_get_digestbyname(salg);
2699 if (!implementation)
2700 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2701
2702 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
2703 if (!n)
2704 return log_oom_debug();
2705
2706 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2707
2708 if (strv_consume(&l, TAKE_PTR(n)) < 0)
2709 return log_oom_debug();
2710 }
2711
2712 *ret = TAKE_PTR(l);
2713 return 0;
2714 #else /* HAVE_OPENSSL */
2715 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2716 #endif
2717 }
2718
2719 /* Hash data into the digest.
2720 *
2721 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2722 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2723 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2724 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2725 *
2726 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2727 * correct for 'alg'.
2728 *
2729 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2730 int tpm2_digest_many(
2731 TPMI_ALG_HASH alg,
2732 TPM2B_DIGEST *digest,
2733 const struct iovec data[],
2734 size_t n_data,
2735 bool extend) {
2736
2737 struct sha256_ctx ctx;
2738
2739 assert(digest);
2740 assert(data || n_data == 0);
2741
2742 if (alg != TPM2_ALG_SHA256)
2743 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2744 "Hash algorithm not supported: 0x%x", alg);
2745
2746 if (extend && digest->size != SHA256_DIGEST_SIZE)
2747 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2748 "Digest size 0x%x, require 0x%x",
2749 digest->size, (unsigned)SHA256_DIGEST_SIZE);
2750
2751 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2752 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
2753
2754 CLEANUP_ERASE(ctx);
2755
2756 sha256_init_ctx(&ctx);
2757
2758 if (extend)
2759 sha256_process_bytes(digest->buffer, digest->size, &ctx);
2760 else {
2761 *digest = (TPM2B_DIGEST){ .size = SHA256_DIGEST_SIZE, };
2762 if (n_data == 0) /* If not extending and no data, return zero hash */
2763 return 0;
2764 }
2765
2766 FOREACH_ARRAY(d, data, n_data)
2767 sha256_process_bytes(d->iov_base, d->iov_len, &ctx);
2768
2769 sha256_finish_ctx(&ctx, digest->buffer);
2770
2771 return 0;
2772 }
2773
2774 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2775 int tpm2_digest_many_digests(
2776 TPMI_ALG_HASH alg,
2777 TPM2B_DIGEST *digest,
2778 const TPM2B_DIGEST data[],
2779 size_t n_data,
2780 bool extend) {
2781
2782 _cleanup_free_ struct iovec *iovecs = NULL;
2783
2784 assert(data || n_data == 0);
2785
2786 iovecs = new(struct iovec, n_data);
2787 if (!iovecs)
2788 return log_oom_debug();
2789
2790 for (size_t i = 0; i < n_data; i++)
2791 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
2792
2793 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
2794 }
2795
2796 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
2797 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
2798 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
2799 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
2800 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2801 *
2802 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2803 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2804 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2805 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2806 *
2807 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2808 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2809 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2810 *
2811 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2812 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2813 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2814 * which we will trim the 0(s) from before sending to the TPM.
2815 */
2816 static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
2817 bool trimmed = false;
2818
2819 assert(auth);
2820
2821 while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
2822 trimmed = true;
2823 auth->size--;
2824 }
2825
2826 if (trimmed)
2827 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2828 }
2829
2830 static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
2831 TPM2B_AUTH auth = {};
2832 int r;
2833
2834 assert(pin);
2835 assert(ret_auth);
2836
2837 r = tpm2_digest_buffer(hash, &auth, pin, strlen(pin), /* extend= */ false);
2838 if (r < 0)
2839 return r;
2840
2841 tpm2_trim_auth_value(&auth);
2842
2843 *ret_auth = TAKE_STRUCT(auth);
2844
2845 return 0;
2846 }
2847
2848 static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
2849 TPM2B_AUTH auth = {};
2850 TSS2_RC rc;
2851 int r;
2852
2853 assert(c);
2854 assert(handle);
2855
2856 if (!pin)
2857 return 0;
2858
2859 CLEANUP_ERASE(auth);
2860
2861 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &auth);
2862 if (r < 0)
2863 return r;
2864
2865 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, &auth);
2866 if (rc != TSS2_RC_SUCCESS)
2867 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2868 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
2869
2870 return 0;
2871 }
2872
2873 static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
2874 TPMA_SESSION flags = 0;
2875 TSS2_RC rc;
2876
2877 assert(c);
2878 assert(session);
2879
2880 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
2881 if (rc != TSS2_RC_SUCCESS)
2882 return false;
2883
2884 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
2885 }
2886
2887 static int tpm2_make_encryption_session(
2888 Tpm2Context *c,
2889 const Tpm2Handle *primary,
2890 const Tpm2Handle *bind_key,
2891 Tpm2Handle **ret_session) {
2892
2893 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
2894 TPMA_SESSION_CONTINUESESSION;
2895 TSS2_RC rc;
2896 int r;
2897
2898 assert(c);
2899 assert(primary);
2900 assert(ret_session);
2901
2902 log_debug("Starting HMAC encryption session.");
2903
2904 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2905 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2906 * recover the salt, which is then used for key derivation. */
2907 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
2908 r = tpm2_handle_new(c, &session);
2909 if (r < 0)
2910 return r;
2911
2912 rc = sym_Esys_StartAuthSession(
2913 c->esys_context,
2914 primary->esys_handle,
2915 bind_key ? bind_key->esys_handle : ESYS_TR_NONE,
2916 ESYS_TR_NONE,
2917 ESYS_TR_NONE,
2918 ESYS_TR_NONE,
2919 NULL,
2920 TPM2_SE_HMAC,
2921 &SESSION_TEMPLATE_SYM_AES_128_CFB,
2922 TPM2_ALG_SHA256,
2923 &session->esys_handle);
2924 if (rc != TSS2_RC_SUCCESS)
2925 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2926 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2927
2928 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2929 * always used for sessions), this provides confidentiality, integrity and replay protection for
2930 * operations that use this session. */
2931 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
2932 if (rc != TSS2_RC_SUCCESS)
2933 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2934 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc));
2935
2936 *ret_session = TAKE_PTR(session);
2937
2938 return 0;
2939 }
2940
2941 static int tpm2_make_policy_session(
2942 Tpm2Context *c,
2943 const Tpm2Handle *primary,
2944 const Tpm2Handle *encryption_session,
2945 Tpm2Handle **ret_session) {
2946
2947 TSS2_RC rc;
2948 int r;
2949
2950 assert(c);
2951 assert(primary);
2952 assert(encryption_session);
2953 assert(ret_session);
2954
2955 if (!tpm2_is_encryption_session(c, encryption_session))
2956 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
2957 "Missing encryption session");
2958
2959 log_debug("Starting policy session.");
2960
2961 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
2962 r = tpm2_handle_new(c, &session);
2963 if (r < 0)
2964 return r;
2965
2966 rc = sym_Esys_StartAuthSession(
2967 c->esys_context,
2968 primary->esys_handle,
2969 ESYS_TR_NONE,
2970 encryption_session->esys_handle,
2971 ESYS_TR_NONE,
2972 ESYS_TR_NONE,
2973 NULL,
2974 TPM2_SE_POLICY,
2975 &SESSION_TEMPLATE_SYM_AES_128_CFB,
2976 TPM2_ALG_SHA256,
2977 &session->esys_handle);
2978 if (rc != TSS2_RC_SUCCESS)
2979 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2980 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2981
2982 *ret_session = TAKE_PTR(session);
2983
2984 return 0;
2985 }
2986
2987 static int find_signature(
2988 JsonVariant *v,
2989 const TPML_PCR_SELECTION *pcr_selection,
2990 const void *fp,
2991 size_t fp_size,
2992 const void *policy,
2993 size_t policy_size,
2994 void *ret_signature,
2995 size_t *ret_signature_size) {
2996
2997 #if HAVE_OPENSSL
2998 JsonVariant *b, *i;
2999 const char *k;
3000 int r;
3001
3002 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3003 * public key, and policy digest. */
3004
3005 if (!json_variant_is_object(v))
3006 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
3007
3008 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
3009 uint32_t pcr_mask = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank);
3010
3011 k = tpm2_hash_alg_to_string(pcr_bank);
3012 if (!k)
3013 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
3014
3015 /* First, find field by bank */
3016 b = json_variant_by_key(v, k);
3017 if (!b)
3018 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
3019
3020 if (!json_variant_is_array(b))
3021 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
3022
3023 /* Now iterate through all signatures known for this bank */
3024 JSON_VARIANT_ARRAY_FOREACH(i, b) {
3025 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
3026 JsonVariant *maskj, *fpj, *sigj, *polj;
3027 size_t fpj_size, polj_size;
3028 uint32_t parsed_mask;
3029
3030 if (!json_variant_is_object(i))
3031 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
3032
3033 /* Check if the PCR mask matches our expectations */
3034 maskj = json_variant_by_key(i, "pcrs");
3035 if (!maskj)
3036 continue;
3037
3038 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
3039 if (r < 0)
3040 return log_debug_errno(r, "Failed to parse JSON PCR mask");
3041
3042 if (parsed_mask != pcr_mask)
3043 continue; /* Not for this PCR mask */
3044
3045 /* Then check if this is for the public key we operate with */
3046 fpj = json_variant_by_key(i, "pkfp");
3047 if (!fpj)
3048 continue;
3049
3050 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
3051 if (r < 0)
3052 return log_debug_errno(r, "Failed to decode fingerprint in JSON data: %m");
3053
3054 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
3055 continue; /* Not for this public key */
3056
3057 /* Finally, check if this is for the PCR policy we expect this to be */
3058 polj = json_variant_by_key(i, "pol");
3059 if (!polj)
3060 continue;
3061
3062 r = json_variant_unhex(polj, &polj_data, &polj_size);
3063 if (r < 0)
3064 return log_debug_errno(r, "Failed to decode policy hash JSON data: %m");
3065
3066 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
3067 continue;
3068
3069 /* This entry matches all our expectations, now return the signature included in it */
3070 sigj = json_variant_by_key(i, "sig");
3071 if (!sigj)
3072 continue;
3073
3074 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
3075 }
3076
3077 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
3078 #else /* HAVE_OPENSSL */
3079 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3080 #endif
3081 }
3082
3083 /* Calculates the "name" of a public key.
3084 *
3085 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3086 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3087 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3088 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3089 * that would also change the key name.
3090 *
3091 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3092 * nameAlg is not TPM2_ALG_SHA256. */
3093 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
3094 TSS2_RC rc;
3095 int r;
3096
3097 assert(public);
3098 assert(ret_name);
3099
3100 r = dlopen_tpm2();
3101 if (r < 0)
3102 return log_debug_errno(r, "TPM2 support not installed: %m");
3103
3104 if (public->nameAlg != TPM2_ALG_SHA256)
3105 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3106 "Unsupported nameAlg: 0x%x",
3107 public->nameAlg);
3108
3109 _cleanup_free_ uint8_t *buf = NULL;
3110 size_t size = 0;
3111
3112 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
3113 if (!buf)
3114 return log_oom_debug();
3115
3116 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
3117 if (rc != TSS2_RC_SUCCESS)
3118 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3119 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
3120
3121 TPM2B_DIGEST digest = {};
3122 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3123 if (r < 0)
3124 return r;
3125
3126 TPMT_HA ha = {
3127 .hashAlg = TPM2_ALG_SHA256,
3128 };
3129 assert(digest.size <= sizeof(ha.digest.sha256));
3130 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3131
3132 TPM2B_NAME name;
3133 size = 0;
3134 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3135 if (rc != TSS2_RC_SUCCESS)
3136 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3137 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
3138 name.size = size;
3139
3140 tpm2_log_debug_name(&name, "Calculated name");
3141
3142 *ret_name = name;
3143
3144 return 0;
3145 }
3146
3147 /* Get the "name" of a key from the TPM.
3148 *
3149 * The "name" of a key is explained above in tpm2_calculate_name().
3150 *
3151 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3152 * public/private keypair. */
3153 static int tpm2_get_name(
3154 Tpm2Context *c,
3155 const Tpm2Handle *handle,
3156 TPM2B_NAME **ret_name) {
3157
3158 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
3159 TSS2_RC rc;
3160
3161 assert(c);
3162 assert(handle);
3163 assert(ret_name);
3164
3165 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
3166 if (rc != TSS2_RC_SUCCESS)
3167 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3168 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
3169
3170 tpm2_log_debug_name(name, "Object name");
3171
3172 *ret_name = TAKE_PTR(name);
3173
3174 return 0;
3175 }
3176
3177 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3178 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
3179 TPM2_CC command = TPM2_CC_PolicyAuthValue;
3180 TSS2_RC rc;
3181 int r;
3182
3183 assert(digest);
3184 assert(digest->size == SHA256_DIGEST_SIZE);
3185
3186 r = dlopen_tpm2();
3187 if (r < 0)
3188 return log_debug_errno(r, "TPM2 support not installed: %m");
3189
3190 uint8_t buf[sizeof(command)];
3191 size_t offset = 0;
3192
3193 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3194 if (rc != TSS2_RC_SUCCESS)
3195 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3196 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
3197
3198 if (offset != sizeof(command))
3199 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3200 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
3201
3202 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
3203 if (r < 0)
3204 return r;
3205
3206 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
3207
3208 return 0;
3209 }
3210
3211 static int tpm2_policy_auth_value(
3212 Tpm2Context *c,
3213 const Tpm2Handle *session,
3214 TPM2B_DIGEST **ret_policy_digest) {
3215
3216 TSS2_RC rc;
3217
3218 assert(c);
3219 assert(session);
3220
3221 log_debug("Adding authValue policy.");
3222
3223 rc = sym_Esys_PolicyAuthValue(
3224 c->esys_context,
3225 session->esys_handle,
3226 ESYS_TR_NONE,
3227 ESYS_TR_NONE,
3228 ESYS_TR_NONE);
3229 if (rc != TSS2_RC_SUCCESS)
3230 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3231 "Failed to add authValue policy to TPM: %s",
3232 sym_Tss2_RC_Decode(rc));
3233
3234 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3235 }
3236
3237 /* Extend 'digest' with the PolicyPCR calculated hash. */
3238 int tpm2_calculate_policy_pcr(
3239 const Tpm2PCRValue *pcr_values,
3240 size_t n_pcr_values,
3241 TPM2B_DIGEST *digest) {
3242
3243 TPM2_CC command = TPM2_CC_PolicyPCR;
3244 TSS2_RC rc;
3245 int r;
3246
3247 assert(pcr_values || n_pcr_values == 0);
3248 assert(digest);
3249 assert(digest->size == SHA256_DIGEST_SIZE);
3250
3251 r = dlopen_tpm2();
3252 if (r < 0)
3253 return log_debug_errno(r, "TPM2 support not installed: %m");
3254
3255 TPML_PCR_SELECTION pcr_selection;
3256 _cleanup_free_ TPM2B_DIGEST *values = NULL;
3257 size_t n_values;
3258 r = tpm2_tpml_pcr_selection_from_pcr_values(pcr_values, n_pcr_values, &pcr_selection, &values, &n_values);
3259 if (r < 0)
3260 return log_debug_errno(r, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3261
3262 TPM2B_DIGEST hash = {};
3263 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, values, n_values, /* extend= */ false);
3264 if (r < 0)
3265 return r;
3266
3267 _cleanup_free_ uint8_t *buf = NULL;
3268 size_t size = 0, maxsize = sizeof(command) + sizeof(pcr_selection);
3269
3270 buf = malloc(maxsize);
3271 if (!buf)
3272 return log_oom_debug();
3273
3274 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
3275 if (rc != TSS2_RC_SUCCESS)
3276 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3277 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
3278
3279 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection, buf, maxsize, &size);
3280 if (rc != TSS2_RC_SUCCESS)
3281 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3282 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
3283
3284 struct iovec data[] = {
3285 IOVEC_MAKE(buf, size),
3286 IOVEC_MAKE(hash.buffer, hash.size),
3287 };
3288 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3289 if (r < 0)
3290 return r;
3291
3292 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
3293
3294 return 0;
3295 }
3296
3297 static int tpm2_policy_pcr(
3298 Tpm2Context *c,
3299 const Tpm2Handle *session,
3300 const TPML_PCR_SELECTION *pcr_selection,
3301 TPM2B_DIGEST **ret_policy_digest) {
3302
3303 TSS2_RC rc;
3304
3305 assert(c);
3306 assert(session);
3307 assert(pcr_selection);
3308
3309 log_debug("Adding PCR hash policy.");
3310
3311 rc = sym_Esys_PolicyPCR(
3312 c->esys_context,
3313 session->esys_handle,
3314 ESYS_TR_NONE,
3315 ESYS_TR_NONE,
3316 ESYS_TR_NONE,
3317 NULL,
3318 pcr_selection);
3319 if (rc != TSS2_RC_SUCCESS)
3320 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3321 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
3322
3323 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3324 }
3325
3326 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3327 int tpm2_calculate_policy_authorize(
3328 const TPM2B_PUBLIC *public,
3329 const TPM2B_DIGEST *policy_ref,
3330 TPM2B_DIGEST *digest) {
3331
3332 TPM2_CC command = TPM2_CC_PolicyAuthorize;
3333 TSS2_RC rc;
3334 int r;
3335
3336 assert(public);
3337 assert(digest);
3338 assert(digest->size == SHA256_DIGEST_SIZE);
3339
3340 r = dlopen_tpm2();
3341 if (r < 0)
3342 return log_debug_errno(r, "TPM2 support not installed: %m");
3343
3344 uint8_t buf[sizeof(command)];
3345 size_t offset = 0;
3346
3347 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3348 if (rc != TSS2_RC_SUCCESS)
3349 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3350 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
3351
3352 if (offset != sizeof(command))
3353 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3354 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
3355
3356 TPM2B_NAME name = {};
3357 r = tpm2_calculate_pubkey_name(&public->publicArea, &name);
3358 if (r < 0)
3359 return r;
3360
3361 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3362 zero(digest->buffer);
3363
3364 struct iovec data[] = {
3365 IOVEC_MAKE(buf, offset),
3366 IOVEC_MAKE(name.name, name.size),
3367 };
3368 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3369 if (r < 0)
3370 return r;
3371
3372 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3373 if (policy_ref)
3374 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
3375 else
3376 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
3377 if (r < 0)
3378 return r;
3379
3380 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
3381
3382 return 0;
3383 }
3384
3385 static int tpm2_policy_authorize(
3386 Tpm2Context *c,
3387 const Tpm2Handle *session,
3388 TPML_PCR_SELECTION *pcr_selection,
3389 const TPM2B_PUBLIC *public,
3390 const void *fp,
3391 size_t fp_size,
3392 JsonVariant *signature_json,
3393 TPM2B_DIGEST **ret_policy_digest) {
3394
3395 TSS2_RC rc;
3396 int r;
3397
3398 assert(c);
3399 assert(session);
3400 assert(pcr_selection);
3401 assert(public);
3402 assert(fp && fp_size > 0);
3403
3404 log_debug("Adding PCR signature policy.");
3405
3406 _cleanup_(tpm2_handle_freep) Tpm2Handle *pubkey_handle = NULL;
3407 r = tpm2_load_external(c, NULL, public, NULL, &pubkey_handle);
3408 if (r < 0)
3409 return r;
3410
3411 /* Acquire the "name" of what we just loaded */
3412 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
3413 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
3414 if (r < 0)
3415 return r;
3416
3417 /* If we have a signature, proceed with verifying the PCR digest */
3418 const TPMT_TK_VERIFIED *check_ticket;
3419 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
3420 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
3421 if (signature_json) {
3422 r = tpm2_policy_pcr(
3423 c,
3424 session,
3425 pcr_selection,
3426 &approved_policy);
3427 if (r < 0)
3428 return r;
3429
3430 _cleanup_free_ void *signature_raw = NULL;
3431 size_t signature_size;
3432
3433 r = find_signature(
3434 signature_json,
3435 pcr_selection,
3436 fp, fp_size,
3437 approved_policy->buffer,
3438 approved_policy->size,
3439 &signature_raw,
3440 &signature_size);
3441 if (r < 0)
3442 return r;
3443
3444 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3445 * hence we need to do the SHA256 part ourselves, first */
3446 TPM2B_DIGEST signature_hash = *approved_policy;
3447 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
3448 if (r < 0)
3449 return r;
3450
3451 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size);
3452 if (r < 0)
3453 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
3454
3455 TPMT_SIGNATURE policy_signature = {
3456 .sigAlg = TPM2_ALG_RSASSA,
3457 .signature.rsassa = {
3458 .hash = TPM2_ALG_SHA256,
3459 .sig = TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw, signature_size),
3460 },
3461 };
3462
3463 rc = sym_Esys_VerifySignature(
3464 c->esys_context,
3465 pubkey_handle->esys_handle,
3466 ESYS_TR_NONE,
3467 ESYS_TR_NONE,
3468 ESYS_TR_NONE,
3469 &signature_hash,
3470 &policy_signature,
3471 &check_ticket_buffer);
3472 if (rc != TSS2_RC_SUCCESS)
3473 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3474 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
3475
3476 check_ticket = check_ticket_buffer;
3477 } else {
3478 /* When enrolling, we pass a NULL ticket */
3479 static const TPMT_TK_VERIFIED check_ticket_null = {
3480 .tag = TPM2_ST_VERIFIED,
3481 .hierarchy = TPM2_RH_OWNER,
3482 };
3483
3484 check_ticket = &check_ticket_null;
3485 }
3486
3487 rc = sym_Esys_PolicyAuthorize(
3488 c->esys_context,
3489 session->esys_handle,
3490 ESYS_TR_NONE,
3491 ESYS_TR_NONE,
3492 ESYS_TR_NONE,
3493 approved_policy,
3494 /* policyRef= */ &(const TPM2B_NONCE) {},
3495 pubkey_name,
3496 check_ticket);
3497 if (rc != TSS2_RC_SUCCESS)
3498 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3499 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
3500
3501 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3502 }
3503
3504 /* Extend 'digest' with the calculated policy hash. */
3505 int tpm2_calculate_sealing_policy(
3506 const Tpm2PCRValue *pcr_values,
3507 size_t n_pcr_values,
3508 const TPM2B_PUBLIC *public,
3509 bool use_pin,
3510 TPM2B_DIGEST *digest) {
3511
3512 int r;
3513
3514 assert(pcr_values || n_pcr_values == 0);
3515 assert(digest);
3516
3517 if (public) {
3518 r = tpm2_calculate_policy_authorize(public, NULL, digest);
3519 if (r < 0)
3520 return r;
3521 }
3522
3523 if (n_pcr_values > 0) {
3524 r = tpm2_calculate_policy_pcr(pcr_values, n_pcr_values, digest);
3525 if (r < 0)
3526 return r;
3527 }
3528
3529 if (use_pin) {
3530 r = tpm2_calculate_policy_auth_value(digest);
3531 if (r < 0)
3532 return r;
3533 }
3534
3535 return 0;
3536 }
3537
3538 static int tpm2_build_sealing_policy(
3539 Tpm2Context *c,
3540 const Tpm2Handle *session,
3541 uint32_t hash_pcr_mask,
3542 uint16_t pcr_bank,
3543 const TPM2B_PUBLIC *public,
3544 const void *fp,
3545 size_t fp_size,
3546 uint32_t pubkey_pcr_mask,
3547 JsonVariant *signature_json,
3548 bool use_pin,
3549 TPM2B_DIGEST **ret_policy_digest) {
3550
3551 int r;
3552
3553 assert(c);
3554 assert(session);
3555 assert(pubkey_pcr_mask == 0 || public);
3556
3557 log_debug("Building sealing policy.");
3558
3559 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
3560 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
3561 if (r < 0)
3562 return r;
3563 if (r == 0)
3564 log_debug("Selected TPM2 PCRs are not initialized on this system.");
3565 }
3566
3567 if (pubkey_pcr_mask != 0) {
3568 TPML_PCR_SELECTION pcr_selection;
3569 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
3570 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
3571 if (r < 0)
3572 return r;
3573 }
3574
3575 if (hash_pcr_mask != 0) {
3576 TPML_PCR_SELECTION pcr_selection;
3577 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
3578 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
3579 if (r < 0)
3580 return r;
3581 }
3582
3583 if (use_pin) {
3584 r = tpm2_policy_auth_value(c, session, NULL);
3585 if (r < 0)
3586 return r;
3587 }
3588
3589 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
3590 if (r < 0)
3591 return r;
3592
3593 return 0;
3594 }
3595
3596 #if HAVE_OPENSSL
3597 static const struct {
3598 TPM2_ECC_CURVE tpm2_ecc_curve_id;
3599 int openssl_ecc_curve_id;
3600 } tpm2_openssl_ecc_curve_table[] = {
3601 { TPM2_ECC_NIST_P192, NID_X9_62_prime192v1, },
3602 { TPM2_ECC_NIST_P224, NID_secp224r1, },
3603 { TPM2_ECC_NIST_P256, NID_X9_62_prime256v1, },
3604 { TPM2_ECC_NIST_P384, NID_secp384r1, },
3605 { TPM2_ECC_NIST_P521, NID_secp521r1, },
3606 { TPM2_ECC_SM2_P256, NID_sm2, },
3607 };
3608
3609 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id, TPM2_ECC_CURVE *ret) {
3610 assert(ret);
3611
3612 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
3613 if (t->openssl_ecc_curve_id == openssl_ecc_curve_id) {
3614 *ret = t->tpm2_ecc_curve_id;
3615 return 0;
3616 }
3617
3618 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3619 "Openssl ECC curve id %d not supported.", openssl_ecc_curve_id);
3620 }
3621
3622 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id, int *ret) {
3623 assert(ret);
3624
3625 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
3626 if (t->tpm2_ecc_curve_id == tpm2_ecc_curve_id) {
3627 *ret = t->openssl_ecc_curve_id;
3628 return 0;
3629 }
3630
3631 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3632 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id);
3633 }
3634
3635 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
3636
3637 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret) {
3638 int r;
3639
3640 assert(public);
3641 assert(ret);
3642
3643 const TPMT_PUBLIC *p = &public->publicArea;
3644 switch (p->type) {
3645 case TPM2_ALG_ECC: {
3646 int curve_id;
3647 r = tpm2_ecc_curve_to_openssl_curve_id(p->parameters.eccDetail.curveID, &curve_id);
3648 if (r < 0)
3649 return r;
3650
3651 const TPMS_ECC_POINT *point = &p->unique.ecc;
3652 return ecc_pkey_from_curve_x_y(
3653 curve_id,
3654 point->x.buffer,
3655 point->x.size,
3656 point->y.buffer,
3657 point->y.size,
3658 ret);
3659 }
3660 case TPM2_ALG_RSA: {
3661 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
3662 * zero indicates that the exponent is the default of 2^16 + 1". */
3663 uint32_t exponent = htobe32(p->parameters.rsaDetail.exponent ?: TPM2_RSA_DEFAULT_EXPONENT);
3664 return rsa_pkey_from_n_e(
3665 p->unique.rsa.buffer,
3666 p->unique.rsa.size,
3667 &exponent,
3668 sizeof(exponent),
3669 ret);
3670 }
3671 default:
3672 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3673 "TPM2 asymmetric algorithm 0x%" PRIx16 " not supported.", p->type);
3674 }
3675 }
3676
3677 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) {
3678 int key_id, r;
3679
3680 assert(pkey);
3681 assert(ret);
3682
3683 TPMT_PUBLIC public = {
3684 .nameAlg = TPM2_ALG_SHA256,
3685 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
3686 .parameters.asymDetail = {
3687 .symmetric.algorithm = TPM2_ALG_NULL,
3688 .scheme.scheme = TPM2_ALG_NULL,
3689 },
3690 };
3691
3692 #if OPENSSL_VERSION_MAJOR >= 3
3693 key_id = EVP_PKEY_get_id(pkey);
3694 #else
3695 key_id = EVP_PKEY_id(pkey);
3696 #endif
3697
3698 switch (key_id) {
3699 case EVP_PKEY_EC: {
3700 public.type = TPM2_ALG_ECC;
3701
3702 int curve_id;
3703 _cleanup_free_ void *x = NULL, *y = NULL;
3704 size_t x_size, y_size;
3705 r = ecc_pkey_to_curve_x_y(pkey, &curve_id, &x, &x_size, &y, &y_size);
3706 if (r < 0)
3707 return log_debug_errno(r, "Could not get ECC key curve/x/y: %m");
3708
3709 TPM2_ECC_CURVE curve;
3710 r = tpm2_ecc_curve_from_openssl_curve_id(curve_id, &curve);
3711 if (r < 0)
3712 return r;
3713
3714 public.parameters.eccDetail.curveID = curve;
3715
3716 public.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
3717
3718 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
3719 if (r < 0)
3720 return log_debug_errno(r, "ECC key x size %zu too large.", x_size);
3721
3722 public.unique.ecc.x = TPM2B_ECC_PARAMETER_MAKE(x, x_size);
3723
3724 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
3725 if (r < 0)
3726 return log_debug_errno(r, "ECC key y size %zu too large.", y_size);
3727
3728 public.unique.ecc.y = TPM2B_ECC_PARAMETER_MAKE(y, y_size);
3729
3730 break;
3731 }
3732 case EVP_PKEY_RSA: {
3733 public.type = TPM2_ALG_RSA;
3734
3735 _cleanup_free_ void *n = NULL, *e = NULL;
3736 size_t n_size, e_size;
3737 r = rsa_pkey_to_n_e(pkey, &n, &n_size, &e, &e_size);
3738 if (r < 0)
3739 return log_debug_errno(r, "Could not get RSA key n/e: %m");
3740
3741 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size);
3742 if (r < 0)
3743 return log_debug_errno(r, "RSA key n size %zu too large.", n_size);
3744
3745 public.unique.rsa = TPM2B_PUBLIC_KEY_RSA_MAKE(n, n_size);
3746 public.parameters.rsaDetail.keyBits = n_size * 8;
3747
3748 if (sizeof(uint32_t) < e_size)
3749 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3750 "RSA key e size %zu too large.", e_size);
3751
3752 uint32_t exponent = 0;
3753 memcpy(&exponent, e, e_size);
3754 exponent = be32toh(exponent) >> (32 - e_size * 8);
3755 if (exponent == TPM2_RSA_DEFAULT_EXPONENT)
3756 exponent = 0;
3757 public.parameters.rsaDetail.exponent = exponent;
3758
3759 break;
3760 }
3761 default:
3762 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3763 "EVP_PKEY type %d not supported.", key_id);
3764 }
3765
3766 *ret = (TPM2B_PUBLIC) {
3767 .size = sizeof(public),
3768 .publicArea = public,
3769 };
3770
3771 return 0;
3772 }
3773 #endif
3774
3775 int tpm2_tpm2b_public_to_fingerprint(
3776 const TPM2B_PUBLIC *public,
3777 void **ret_fingerprint,
3778 size_t *ret_fingerprint_size) {
3779
3780 #if HAVE_OPENSSL
3781 int r;
3782
3783 assert(public);
3784 assert(ret_fingerprint);
3785 assert(ret_fingerprint_size);
3786
3787 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
3788 r = tpm2_tpm2b_public_to_openssl_pkey(public, &pkey);
3789 if (r < 0)
3790 return r;
3791
3792 /* Hardcode fingerprint to SHA256 */
3793 return pubkey_fingerprint(pkey, EVP_sha256(), ret_fingerprint, ret_fingerprint_size);
3794 #else
3795 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3796 #endif
3797 }
3798
3799 int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) {
3800 #if HAVE_OPENSSL
3801 int r;
3802
3803 assert(pem);
3804 assert(ret);
3805
3806 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
3807 r = openssl_pkey_from_pem(pem, pem_size, &pkey);
3808 if (r < 0)
3809 return r;
3810
3811 return tpm2_tpm2b_public_from_openssl_pkey(pkey, ret);
3812 #else
3813 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3814 #endif
3815 }
3816
3817 /* Marshal the public and private objects into a single nonstandard 'blob'. This is not a (publicly) standard
3818 * format, this is specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
3819 * tpm2_unmarshal_blob(). */
3820 static int tpm2_marshal_blob(
3821 const TPM2B_PUBLIC *public,
3822 const TPM2B_PRIVATE *private,
3823 void **ret_blob,
3824 size_t *ret_blob_size) {
3825
3826 TSS2_RC rc;
3827
3828 assert(public);
3829 assert(private);
3830 assert(ret_blob);
3831 assert(ret_blob_size);
3832
3833 size_t max_size = sizeof(*private) + sizeof(*public);
3834
3835 _cleanup_free_ void *blob = malloc(max_size);
3836 if (!blob)
3837 return log_oom_debug();
3838
3839 size_t blob_size = 0;
3840 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
3841 if (rc != TSS2_RC_SUCCESS)
3842 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3843 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
3844
3845 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
3846 if (rc != TSS2_RC_SUCCESS)
3847 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3848 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
3849
3850 *ret_blob = TAKE_PTR(blob);
3851 *ret_blob_size = blob_size;
3852
3853 return 0;
3854 }
3855
3856 /* Unmarshal the 'blob' into public and private objects. This is not a (publicly) standard format, this is
3857 * specific to how we currently store the sealed object. This expects the 'blob' to have been created by
3858 * tpm2_marshal_blob(). */
3859 static int tpm2_unmarshal_blob(
3860 const void *blob,
3861 size_t blob_size,
3862 TPM2B_PUBLIC *ret_public,
3863 TPM2B_PRIVATE *ret_private) {
3864
3865 TSS2_RC rc;
3866
3867 assert(blob);
3868 assert(ret_public);
3869 assert(ret_private);
3870
3871 TPM2B_PRIVATE private = {};
3872 size_t offset = 0;
3873 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
3874 if (rc != TSS2_RC_SUCCESS)
3875 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3876 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
3877
3878 TPM2B_PUBLIC public = {};
3879 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
3880 if (rc != TSS2_RC_SUCCESS)
3881 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3882 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
3883
3884 *ret_public = public;
3885 *ret_private = private;
3886
3887 return 0;
3888 }
3889
3890 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
3891 * across restarts of the TPM or reboots (assuming the handle is persistent). */
3892 static int tpm2_serialize(
3893 Tpm2Context *c,
3894 const Tpm2Handle *handle,
3895 void **ret_serialized,
3896 size_t *ret_serialized_size) {
3897
3898 TSS2_RC rc;
3899
3900 assert(c);
3901 assert(handle);
3902 assert(ret_serialized);
3903 assert(ret_serialized_size);
3904
3905 _cleanup_(Esys_Freep) unsigned char *serialized = NULL;
3906 size_t size = 0;
3907 rc = sym_Esys_TR_Serialize(c->esys_context, handle->esys_handle, &serialized, &size);
3908 if (rc != TSS2_RC_SUCCESS)
3909 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3910 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc));
3911
3912 *ret_serialized = TAKE_PTR(serialized);
3913 *ret_serialized_size = size;
3914
3915 return 0;
3916 }
3917
3918 static int tpm2_deserialize(
3919 Tpm2Context *c,
3920 const void *serialized,
3921 size_t serialized_size,
3922 Tpm2Handle **ret_handle) {
3923
3924 TSS2_RC rc;
3925 int r;
3926
3927 assert(c);
3928 assert(serialized);
3929 assert(ret_handle);
3930
3931 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
3932 r = tpm2_handle_new(c, &handle);
3933 if (r < 0)
3934 return r;
3935
3936 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
3937 handle->flush = false;
3938
3939 rc = sym_Esys_TR_Deserialize(c->esys_context, serialized, serialized_size, &handle->esys_handle);
3940 if (rc != TSS2_RC_SUCCESS)
3941 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3942 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc));
3943
3944 *ret_handle = TAKE_PTR(handle);
3945
3946 return 0;
3947 }
3948
3949 int tpm2_seal(Tpm2Context *c,
3950 uint32_t seal_key_handle,
3951 const TPM2B_DIGEST *policy,
3952 const char *pin,
3953 void **ret_secret,
3954 size_t *ret_secret_size,
3955 void **ret_blob,
3956 size_t *ret_blob_size,
3957 uint16_t *ret_primary_alg,
3958 void **ret_srk_buf,
3959 size_t *ret_srk_buf_size) {
3960
3961 uint16_t primary_alg = 0;
3962 int r;
3963
3964 assert(ret_secret);
3965 assert(ret_secret_size);
3966 assert(ret_blob);
3967 assert(ret_blob_size);
3968
3969 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3970 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
3971 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3972 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3973 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3974 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3975 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3976 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3977 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3978 * LUKS2 JSON header.
3979 *
3980 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3981 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3982 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3983 * binding the unlocking to the TPM2 chip. */
3984
3985 usec_t start = now(CLOCK_MONOTONIC);
3986
3987 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3988 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3989 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
3990 TPMT_PUBLIC hmac_template = {
3991 .type = TPM2_ALG_KEYEDHASH,
3992 .nameAlg = TPM2_ALG_SHA256,
3993 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
3994 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
3995 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
3996 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
3997 };
3998
3999 TPMS_SENSITIVE_CREATE hmac_sensitive = {
4000 .data.size = hmac_template.unique.keyedHash.size,
4001 };
4002
4003 CLEANUP_ERASE(hmac_sensitive);
4004
4005 if (pin) {
4006 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &hmac_sensitive.userAuth);
4007 if (r < 0)
4008 return r;
4009 }
4010
4011 assert(sizeof(hmac_sensitive.data.buffer) >= hmac_sensitive.data.size);
4012
4013 (void) tpm2_credit_random(c);
4014
4015 log_debug("Generating secret key data.");
4016
4017 r = crypto_random_bytes(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
4018 if (r < 0)
4019 return log_debug_errno(r, "Failed to generate secret key: %m");
4020
4021 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
4022 if (ret_srk_buf) {
4023 _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
4024
4025 if (IN_SET(seal_key_handle, 0, TPM2_SRK_HANDLE)) {
4026 r = tpm2_get_or_create_srk(
4027 c,
4028 /* session= */ NULL,
4029 &primary_public,
4030 /* ret_name= */ NULL,
4031 /* ret_qname= */ NULL,
4032 &primary_handle);
4033 if (r < 0)
4034 return r;
4035 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle), TPM2_HT_TRANSIENT, TPM2_HT_PERSISTENT)) {
4036 r = tpm2_index_to_handle(
4037 c,
4038 seal_key_handle,
4039 /* session= */ NULL,
4040 &primary_public,
4041 /* ret_name= */ NULL,
4042 /* ret_qname= */ NULL,
4043 &primary_handle);
4044 if (r < 0)
4045 return r;
4046 if (r == 0)
4047 /* We do NOT automatically create anything other than the SRK */
4048 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
4049 "No handle found at index 0x%" PRIx32, seal_key_handle);
4050 } else
4051 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
4052 "Seal key handle 0x%" PRIx32 " is neither transient nor persistent.",
4053 seal_key_handle);
4054
4055 primary_alg = primary_public->publicArea.type;
4056 } else {
4057 if (seal_key_handle != 0)
4058 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
4059
4060 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
4061 primary_alg = TPM2_ALG_ECC;
4062
4063 TPM2B_PUBLIC template = {
4064 .size = sizeof(TPMT_PUBLIC),
4065 };
4066 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
4067 if (r < 0)
4068 return log_debug_errno(r, "Could not get legacy ECC template: %m");
4069
4070 if (!tpm2_supports_tpmt_public(c, &template.publicArea)) {
4071 primary_alg = TPM2_ALG_RSA;
4072
4073 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
4074 if (r < 0)
4075 return log_debug_errno(r, "Could not get legacy RSA template: %m");
4076
4077 if (!tpm2_supports_tpmt_public(c, &template.publicArea))
4078 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4079 "TPM does not support either ECC or RSA legacy template.");
4080 }
4081
4082 r = tpm2_create_primary(
4083 c,
4084 /* session= */ NULL,
4085 &template,
4086 /* sensitive= */ NULL,
4087 /* ret_public= */ NULL,
4088 &primary_handle);
4089 if (r < 0)
4090 return r;
4091 }
4092
4093 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
4094 r = tpm2_make_encryption_session(c, primary_handle, /* bind_key= */ NULL, &encryption_session);
4095 if (r < 0)
4096 return r;
4097
4098 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
4099 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
4100 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
4101 if (r < 0)
4102 return r;
4103
4104 _cleanup_(erase_and_freep) void *secret = NULL;
4105 secret = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
4106 if (!secret)
4107 return log_oom_debug();
4108
4109 log_debug("Marshalling private and public part of HMAC key.");
4110
4111 _cleanup_free_ void *blob = NULL;
4112 size_t blob_size = 0;
4113 r = tpm2_marshal_blob(public, private, &blob, &blob_size);
4114 if (r < 0)
4115 return log_debug_errno(r, "Could not create sealed blob: %m");
4116
4117 if (DEBUG_LOGGING)
4118 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
4119
4120 _cleanup_free_ void *srk_buf = NULL;
4121 size_t srk_buf_size = 0;
4122 if (ret_srk_buf) {
4123 _cleanup_(Esys_Freep) void *tmp = NULL;
4124 r = tpm2_serialize(c, primary_handle, &tmp, &srk_buf_size);
4125 if (r < 0)
4126 return r;
4127
4128 /*
4129 * make a copy since we don't want the caller to understand that
4130 * ESYS allocated the pointer. It would make tracking what deallocator
4131 * to use for srk_buf in which context a PITA.
4132 */
4133 srk_buf = memdup(tmp, srk_buf_size);
4134 if (!srk_buf)
4135 return log_oom_debug();
4136
4137 *ret_srk_buf = TAKE_PTR(srk_buf);
4138 *ret_srk_buf_size = srk_buf_size;
4139 }
4140
4141 *ret_secret = TAKE_PTR(secret);
4142 *ret_secret_size = hmac_sensitive.data.size;
4143 *ret_blob = TAKE_PTR(blob);
4144 *ret_blob_size = blob_size;
4145
4146 if (ret_primary_alg)
4147 *ret_primary_alg = primary_alg;
4148
4149 return 0;
4150 }
4151
4152 #define RETRY_UNSEAL_MAX 30u
4153
4154 int tpm2_unseal(Tpm2Context *c,
4155 uint32_t hash_pcr_mask,
4156 uint16_t pcr_bank,
4157 const void *pubkey,
4158 size_t pubkey_size,
4159 uint32_t pubkey_pcr_mask,
4160 JsonVariant *signature,
4161 const char *pin,
4162 uint16_t primary_alg,
4163 const void *blob,
4164 size_t blob_size,
4165 const void *known_policy_hash,
4166 size_t known_policy_hash_size,
4167 const void *srk_buf,
4168 size_t srk_buf_size,
4169 void **ret_secret,
4170 size_t *ret_secret_size) {
4171
4172 TSS2_RC rc;
4173 int r;
4174
4175 assert(blob);
4176 assert(blob_size > 0);
4177 assert(known_policy_hash_size == 0 || known_policy_hash);
4178 assert(pubkey_size == 0 || pubkey);
4179 assert(ret_secret);
4180 assert(ret_secret_size);
4181
4182 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
4183 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
4184
4185 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
4186 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
4187 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
4188 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
4189 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
4190 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
4191 * and use it to unlock the LUKS2 volume. */
4192
4193 usec_t start = now(CLOCK_MONOTONIC);
4194
4195 TPM2B_PUBLIC public;
4196 TPM2B_PRIVATE private;
4197 r = tpm2_unmarshal_blob(blob, blob_size, &public, &private);
4198 if (r < 0)
4199 return log_debug_errno(r, "Could not extract parts from blob: %m");
4200
4201 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
4202 * so we need to handle that legacy situation. */
4203 if (pcr_bank == UINT16_MAX) {
4204 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
4205 if (r < 0)
4206 return r;
4207 }
4208
4209 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
4210 if (srk_buf) {
4211 r = tpm2_deserialize(c, srk_buf, srk_buf_size, &primary_handle);
4212 if (r < 0)
4213 return r;
4214 } else if (primary_alg != 0) {
4215 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
4216 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
4217 if (r < 0)
4218 return log_debug_errno(r, "Could not get legacy template: %m");
4219
4220 r = tpm2_create_primary(
4221 c,
4222 /* session= */ NULL,
4223 &template,
4224 /* sensitive= */ NULL,
4225 /* ret_public= */ NULL,
4226 &primary_handle);
4227 if (r < 0)
4228 return r;
4229 } else
4230 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
4231 "No SRK or primary alg provided.");
4232
4233 log_debug("Loading HMAC key into TPM.");
4234
4235 /*
4236 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
4237 * gives you back a different key, the session initiation will fail. In the
4238 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
4239 * provides protections.
4240 */
4241 _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
4242 r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
4243 if (r < 0)
4244 return r;
4245
4246 TPM2B_PUBLIC pubkey_tpm2b;
4247 _cleanup_free_ void *fp = NULL;
4248 size_t fp_size = 0;
4249 if (pubkey) {
4250 r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &pubkey_tpm2b);
4251 if (r < 0)
4252 return log_debug_errno(r, "Could not create TPMT_PUBLIC: %m");
4253
4254 r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp, &fp_size);
4255 if (r < 0)
4256 return log_debug_errno(r, "Could not get key fingerprint: %m");
4257 }
4258
4259 /*
4260 * if a pin is set for the seal object, use it to bind the session
4261 * key to that object. This prevents active bus interposers from
4262 * faking a TPM and seeing the unsealed value. An active interposer
4263 * could fake a TPM, satisfying the encrypted session, and just
4264 * forward everything to the *real* TPM.
4265 */
4266 r = tpm2_set_auth(c, hmac_key, pin);
4267 if (r < 0)
4268 return r;
4269
4270 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
4271 r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
4272 if (r < 0)
4273 return r;
4274
4275 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
4276 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
4277 _cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
4278 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
4279 r = tpm2_make_policy_session(
4280 c,
4281 primary_handle,
4282 encryption_session,
4283 &policy_session);
4284 if (r < 0)
4285 return r;
4286
4287 r = tpm2_build_sealing_policy(
4288 c,
4289 policy_session,
4290 hash_pcr_mask,
4291 pcr_bank,
4292 pubkey ? &pubkey_tpm2b : NULL,
4293 fp, fp_size,
4294 pubkey_pcr_mask,
4295 signature,
4296 !!pin,
4297 &policy_digest);
4298 if (r < 0)
4299 return r;
4300
4301 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
4302 * wait until the TPM2 tells us to go away. */
4303 if (known_policy_hash_size > 0 &&
4304 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
4305 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
4306 "Current policy digest does not match stored policy digest, cancelling "
4307 "TPM2 authentication attempt.");
4308
4309 log_debug("Unsealing HMAC key.");
4310
4311 rc = sym_Esys_Unseal(
4312 c->esys_context,
4313 hmac_key->esys_handle,
4314 policy_session->esys_handle,
4315 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
4316 ESYS_TR_NONE,
4317 &unsealed);
4318 if (rc == TSS2_RC_SUCCESS)
4319 break;
4320 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
4321 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4322 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
4323 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
4324 }
4325
4326 _cleanup_(erase_and_freep) char *secret = NULL;
4327 secret = memdup(unsealed->buffer, unsealed->size);
4328 explicit_bzero_safe(unsealed->buffer, unsealed->size);
4329 if (!secret)
4330 return log_oom_debug();
4331
4332 if (DEBUG_LOGGING)
4333 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
4334
4335 *ret_secret = TAKE_PTR(secret);
4336 *ret_secret_size = unsealed->size;
4337
4338 return 0;
4339 }
4340
4341 #endif
4342
4343 int tpm2_list_devices(void) {
4344 #if HAVE_TPM2
4345 _cleanup_(table_unrefp) Table *t = NULL;
4346 _cleanup_closedir_ DIR *d = NULL;
4347 int r;
4348
4349 r = dlopen_tpm2();
4350 if (r < 0)
4351 return log_error_errno(r, "TPM2 support is not installed.");
4352
4353 t = table_new("path", "device", "driver");
4354 if (!t)
4355 return log_oom();
4356
4357 d = opendir("/sys/class/tpmrm");
4358 if (!d) {
4359 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
4360 if (errno != ENOENT)
4361 return -errno;
4362 } else {
4363 for (;;) {
4364 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
4365 struct dirent *de;
4366
4367 de = readdir_no_dot(d);
4368 if (!de)
4369 break;
4370
4371 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
4372 if (!device_path)
4373 return log_oom();
4374
4375 r = readlink_malloc(device_path, &device);
4376 if (r < 0)
4377 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
4378 else {
4379 driver_path = path_join(device_path, "driver");
4380 if (!driver_path)
4381 return log_oom();
4382
4383 r = readlink_malloc(driver_path, &driver);
4384 if (r < 0)
4385 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
4386 }
4387
4388 node = path_join("/dev", de->d_name);
4389 if (!node)
4390 return log_oom();
4391
4392 r = table_add_many(
4393 t,
4394 TABLE_PATH, node,
4395 TABLE_STRING, device ? last_path_component(device) : NULL,
4396 TABLE_STRING, driver ? last_path_component(driver) : NULL);
4397 if (r < 0)
4398 return table_log_add_error(r);
4399 }
4400 }
4401
4402 if (table_get_rows(t) <= 1) {
4403 log_info("No suitable TPM2 devices found.");
4404 return 0;
4405 }
4406
4407 r = table_print(t, stdout);
4408 if (r < 0)
4409 return log_error_errno(r, "Failed to show device table: %m");
4410
4411 return 0;
4412 #else
4413 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4414 "TPM2 not supported on this build.");
4415 #endif
4416 }
4417
4418 int tpm2_find_device_auto(char **ret) {
4419 #if HAVE_TPM2
4420 _cleanup_closedir_ DIR *d = NULL;
4421 int r;
4422
4423 r = dlopen_tpm2();
4424 if (r < 0)
4425 return log_debug_errno(r, "TPM2 support is not installed.");
4426
4427 d = opendir("/sys/class/tpmrm");
4428 if (!d) {
4429 log_debug_errno(errno, "Failed to open /sys/class/tpmrm: %m");
4430 if (errno != ENOENT)
4431 return -errno;
4432 } else {
4433 _cleanup_free_ char *node = NULL;
4434
4435 for (;;) {
4436 struct dirent *de;
4437
4438 de = readdir_no_dot(d);
4439 if (!de)
4440 break;
4441
4442 if (node)
4443 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
4444 "More than one TPM2 (tpmrm) device found.");
4445
4446 node = path_join("/dev", de->d_name);
4447 if (!node)
4448 return log_oom_debug();
4449 }
4450
4451 if (node) {
4452 *ret = TAKE_PTR(node);
4453 return 0;
4454 }
4455 }
4456
4457 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
4458 #else
4459 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4460 "TPM2 not supported on this build.");
4461 #endif
4462 }
4463
4464 #if HAVE_TPM2
4465 static const char* tpm2_userspace_event_type_table[_TPM2_USERSPACE_EVENT_TYPE_MAX] = {
4466 [TPM2_EVENT_PHASE] = "phase",
4467 [TPM2_EVENT_FILESYSTEM] = "filesystem",
4468 [TPM2_EVENT_VOLUME_KEY] = "volume-key",
4469 [TPM2_EVENT_MACHINE_ID] = "machine-id",
4470 };
4471
4472 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
4473
4474 const char *tpm2_userspace_log_path(void) {
4475 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
4476 }
4477
4478 static int tpm2_userspace_log_open(void) {
4479 _cleanup_close_ int fd = -EBADF;
4480 struct stat st;
4481 const char *e;
4482 int r;
4483
4484 e = tpm2_userspace_log_path();
4485 (void) mkdir_parents(e, 0755);
4486
4487 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
4488 * because we use BSD file locking on it, and if anyone but root can access the file they can also
4489 * lock it, which we want to avoid. */
4490 fd = open(e, O_CREAT|O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
4491 if (fd < 0)
4492 return log_debug_errno(errno, "Failed to open TPM log file '%s' for writing, ignoring: %m", e);
4493
4494 if (flock(fd, LOCK_EX) < 0)
4495 return log_debug_errno(errno, "Failed to lock TPM log file '%s', ignoring: %m", e);
4496
4497 if (fstat(fd, &st) < 0)
4498 return log_debug_errno(errno, "Failed to fstat TPM log file '%s', ignoring: %m", e);
4499
4500 r = stat_verify_regular(&st);
4501 if (r < 0)
4502 return log_debug_errno(r, "TPM log file '%s' is not regular, ignoring: %m", e);
4503
4504 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
4505 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
4506 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
4507 * our assumed backend fs) doesn't know user xattrs. */
4508 if (st.st_mode & S_ISVTX)
4509 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "TPM log file '%s' aborted, ignoring.", e);
4510
4511 if (fchmod(fd, 0600 | S_ISVTX) < 0)
4512 return log_debug_errno(errno, "Failed to chmod() TPM log file '%s', ignoring: %m", e);
4513
4514 return TAKE_FD(fd);
4515 }
4516
4517 static int tpm2_userspace_log(
4518 int fd,
4519 unsigned pcr_index,
4520 const TPML_DIGEST_VALUES *values,
4521 Tpm2UserspaceEventType event_type,
4522 const char *description) {
4523
4524 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *array = NULL;
4525 _cleanup_free_ char *f = NULL;
4526 sd_id128_t boot_id;
4527 int r;
4528
4529 assert(values);
4530 assert(values->count > 0);
4531
4532 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
4533 * Format – the JSON flavour –
4534 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
4535 * ways from it, specifically:
4536 *
4537 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
4538 * through the whole logs (include firmware logs) before knowing what the next value is we should
4539 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
4540 * it in when it uses the data.
4541 *
4542 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
4543 * JSON array would mean that for each appending we'd have to read the whole log file fully into
4544 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
4545 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
4546 *
4547 * It should be possible to convert this format in a relatively straight-forward way into the
4548 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
4549 * determined from the full dataset.
4550 *
4551 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
4552 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
4553 * timestamp which can be used to order this measurement against possibly other measurements
4554 * independently done by other subsystems on the system.
4555 */
4556
4557 if (fd < 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
4558 return 0;
4559
4560 for (size_t i = 0; i < values->count; i++) {
4561 const EVP_MD *implementation;
4562 const char *a;
4563
4564 assert_se(a = tpm2_hash_alg_to_string(values->digests[i].hashAlg));
4565 assert_se(implementation = EVP_get_digestbyname(a));
4566
4567 r = json_variant_append_arrayb(
4568 &array, JSON_BUILD_OBJECT(
4569 JSON_BUILD_PAIR_STRING("hashAlg", a),
4570 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values->digests[i].digest, EVP_MD_size(implementation)))));
4571 if (r < 0)
4572 return log_debug_errno(r, "Failed to append digest object to JSON array: %m");
4573 }
4574
4575 assert(array);
4576
4577 r = sd_id128_get_boot(&boot_id);
4578 if (r < 0)
4579 return log_debug_errno(r, "Failed to acquire boot ID: %m");
4580
4581 r = json_build(&v, JSON_BUILD_OBJECT(
4582 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index)),
4583 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array)),
4584 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
4585 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
4586 JSON_BUILD_PAIR_CONDITION(description, "string", JSON_BUILD_STRING(description)),
4587 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id)),
4588 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME))),
4589 JSON_BUILD_PAIR_CONDITION(event_type >= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type)))))));
4590 if (r < 0)
4591 return log_debug_errno(r, "Failed to build log record JSON: %m");
4592
4593 r = json_variant_format(v, JSON_FORMAT_SEQ, &f);
4594 if (r < 0)
4595 return log_debug_errno(r, "Failed to format JSON: %m");
4596
4597 if (lseek(fd, 0, SEEK_END) < 0)
4598 return log_debug_errno(errno, "Failed to seek to end of JSON log: %m");
4599
4600 r = loop_write(fd, f, SIZE_MAX);
4601 if (r < 0)
4602 return log_debug_errno(r, "Failed to write JSON data to log: %m");
4603
4604 if (fsync(fd) < 0)
4605 return log_debug_errno(errno, "Failed to sync JSON data: %m");
4606
4607 /* Unset S_ISVTX again */
4608 if (fchmod(fd, 0600) < 0)
4609 return log_debug_errno(errno, "Failed to chmod() TPM log file, ignoring: %m");
4610
4611 r = fsync_full(fd);
4612 if (r < 0)
4613 return log_debug_errno(r, "Failed to sync JSON log: %m");
4614
4615 return 1;
4616 }
4617
4618 int tpm2_extend_bytes(
4619 Tpm2Context *c,
4620 char **banks,
4621 unsigned pcr_index,
4622 const void *data,
4623 size_t data_size,
4624 const void *secret,
4625 size_t secret_size,
4626 Tpm2UserspaceEventType event_type,
4627 const char *description) {
4628
4629 #if HAVE_OPENSSL
4630 _cleanup_close_ int log_fd = -EBADF;
4631 TPML_DIGEST_VALUES values = {};
4632 TSS2_RC rc;
4633
4634 assert(c);
4635 assert(data || data_size == 0);
4636 assert(secret || secret_size == 0);
4637
4638 if (data_size == SIZE_MAX)
4639 data_size = strlen(data);
4640 if (secret_size == SIZE_MAX)
4641 secret_size = strlen(secret);
4642
4643 if (pcr_index >= TPM2_PCRS_MAX)
4644 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
4645
4646 if (strv_isempty(banks))
4647 return 0;
4648
4649 STRV_FOREACH(bank, banks) {
4650 const EVP_MD *implementation;
4651 int id;
4652
4653 assert_se(implementation = EVP_get_digestbyname(*bank));
4654
4655 if (values.count >= ELEMENTSOF(values.digests))
4656 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
4657
4658 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
4659 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
4660
4661 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
4662 if (id < 0)
4663 return log_debug_errno(id, "Can't map hash name to TPM2.");
4664
4665 values.digests[values.count].hashAlg = id;
4666
4667 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
4668 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
4669 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
4670 * secret for other purposes, maybe because it needs a shorter secret derived from it for
4671 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
4672 * private non-secret string instead. */
4673 if (secret_size > 0) {
4674 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
4675 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
4676 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
4677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
4678
4679 values.count++;
4680 }
4681
4682 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
4683 * and our measurement and change either */
4684 log_fd = tpm2_userspace_log_open();
4685
4686 rc = sym_Esys_PCR_Extend(
4687 c->esys_context,
4688 ESYS_TR_PCR0 + pcr_index,
4689 ESYS_TR_PASSWORD,
4690 ESYS_TR_NONE,
4691 ESYS_TR_NONE,
4692 &values);
4693 if (rc != TSS2_RC_SUCCESS)
4694 return log_debug_errno(
4695 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4696 "Failed to measure into PCR %u: %s",
4697 pcr_index,
4698 sym_Tss2_RC_Decode(rc));
4699
4700 /* Now, write what we just extended to the log, too. */
4701 (void) tpm2_userspace_log(log_fd, pcr_index, &values, event_type, description);
4702
4703 return 0;
4704 #else /* HAVE_OPENSSL */
4705 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
4706 #endif
4707 }
4708 #endif
4709
4710 char *tpm2_pcr_mask_to_string(uint32_t mask) {
4711 _cleanup_free_ char *s = NULL;
4712
4713 FOREACH_PCR_IN_MASK(n, mask)
4714 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
4715 return NULL;
4716
4717 if (!s)
4718 return strdup("");
4719
4720 return TAKE_PTR(s);
4721 }
4722
4723 int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
4724 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
4725 int r;
4726
4727 assert(ret);
4728
4729 for (size_t i = 0; i < TPM2_PCRS_MAX; i++) {
4730 _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
4731
4732 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
4733 continue;
4734
4735 r = json_variant_new_integer(&e, i);
4736 if (r < 0)
4737 return r;
4738
4739 r = json_variant_append_array(&a, e);
4740 if (r < 0)
4741 return r;
4742 }
4743
4744 if (!a)
4745 return json_variant_new_array(ret, NULL, 0);
4746
4747 *ret = TAKE_PTR(a);
4748 return 0;
4749 }
4750
4751 int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
4752 JsonVariant *e;
4753 uint32_t mask = 0;
4754
4755 if (!json_variant_is_array(v))
4756 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
4757
4758 JSON_VARIANT_ARRAY_FOREACH(e, v) {
4759 uint64_t u;
4760
4761 if (!json_variant_is_unsigned(e))
4762 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
4763
4764 u = json_variant_unsigned(e);
4765 if (u >= TPM2_PCRS_MAX)
4766 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
4767
4768 mask |= UINT32_C(1) << u;
4769 }
4770
4771 if (ret)
4772 *ret = mask;
4773
4774 return 0;
4775 }
4776
4777 int tpm2_make_luks2_json(
4778 int keyslot,
4779 uint32_t hash_pcr_mask,
4780 uint16_t pcr_bank,
4781 const void *pubkey,
4782 size_t pubkey_size,
4783 uint32_t pubkey_pcr_mask,
4784 uint16_t primary_alg,
4785 const void *blob,
4786 size_t blob_size,
4787 const void *policy_hash,
4788 size_t policy_hash_size,
4789 const void *salt,
4790 size_t salt_size,
4791 const void *srk_buf,
4792 size_t srk_buf_size,
4793 TPM2Flags flags,
4794 JsonVariant **ret) {
4795
4796 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
4797 _cleanup_free_ char *keyslot_as_string = NULL;
4798 int r;
4799
4800 assert(blob || blob_size == 0);
4801 assert(policy_hash || policy_hash_size == 0);
4802 assert(pubkey || pubkey_size == 0);
4803
4804 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
4805 return -ENOMEM;
4806
4807 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
4808 if (r < 0)
4809 return r;
4810
4811 if (pubkey_pcr_mask != 0) {
4812 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
4813 if (r < 0)
4814 return r;
4815 }
4816
4817 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
4818 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
4819 * object should use "_" rather than "-" in field names. */
4820
4821 r = json_build(&v,
4822 JSON_BUILD_OBJECT(
4823 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
4824 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
4825 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
4826 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
4827 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
4828 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg))),
4829 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
4830 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
4831 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
4832 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
4833 JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size)),
4834 JSON_BUILD_PAIR_CONDITION(srk_buf, "tpm2_srk", JSON_BUILD_BASE64(srk_buf, srk_buf_size))));
4835 if (r < 0)
4836 return r;
4837
4838 if (ret)
4839 *ret = TAKE_PTR(v);
4840
4841 return keyslot;
4842 }
4843
4844 int tpm2_parse_luks2_json(
4845 JsonVariant *v,
4846 int *ret_keyslot,
4847 uint32_t *ret_hash_pcr_mask,
4848 uint16_t *ret_pcr_bank,
4849 void **ret_pubkey,
4850 size_t *ret_pubkey_size,
4851 uint32_t *ret_pubkey_pcr_mask,
4852 uint16_t *ret_primary_alg,
4853 void **ret_blob,
4854 size_t *ret_blob_size,
4855 void **ret_policy_hash,
4856 size_t *ret_policy_hash_size,
4857 void **ret_salt,
4858 size_t *ret_salt_size,
4859 void **ret_srk_buf,
4860 size_t *ret_srk_buf_size,
4861 TPM2Flags *ret_flags) {
4862
4863 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
4864 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
4865 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
4866 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
4867 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
4868 int r, keyslot = -1;
4869 TPM2Flags flags = 0;
4870 JsonVariant *w;
4871
4872 assert(v);
4873
4874 if (ret_keyslot) {
4875 keyslot = cryptsetup_get_keyslot_from_token(v);
4876 if (keyslot < 0) {
4877 /* Return a recognizable error when parsing this field, so that callers can handle parsing
4878 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
4879 * spec */
4880 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4881 return -EUCLEAN;
4882 }
4883 }
4884
4885 w = json_variant_by_key(v, "tpm2-pcrs");
4886 if (!w)
4887 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
4888
4889 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
4890 if (r < 0)
4891 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
4892
4893 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4894 * to SHA256. */
4895 w = json_variant_by_key(v, "tpm2-pcr-bank");
4896 if (w) {
4897 /* The PCR bank field is optional */
4898
4899 if (!json_variant_is_string(w))
4900 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
4901
4902 r = tpm2_hash_alg_from_string(json_variant_string(w));
4903 if (r < 0)
4904 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
4905
4906 pcr_bank = r;
4907 }
4908
4909 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4910 * the algorithm was hardcoded to ECC. */
4911 w = json_variant_by_key(v, "tpm2-primary-alg");
4912 if (w) {
4913 /* The primary key algorithm is optional */
4914
4915 if (!json_variant_is_string(w))
4916 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
4917
4918 r = tpm2_asym_alg_from_string(json_variant_string(w));
4919 if (r < 0)
4920 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
4921
4922 primary_alg = r;
4923 }
4924
4925 w = json_variant_by_key(v, "tpm2-blob");
4926 if (!w)
4927 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
4928
4929 r = json_variant_unbase64(w, &blob, &blob_size);
4930 if (r < 0)
4931 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
4932
4933 w = json_variant_by_key(v, "tpm2-policy-hash");
4934 if (!w)
4935 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4936
4937 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
4938 if (r < 0)
4939 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
4940
4941 w = json_variant_by_key(v, "tpm2-pin");
4942 if (w) {
4943 if (!json_variant_is_boolean(w))
4944 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
4945
4946 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
4947 }
4948
4949 w = json_variant_by_key(v, "tpm2_salt");
4950 if (w) {
4951 r = json_variant_unbase64(w, &salt, &salt_size);
4952 if (r < 0)
4953 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
4954 }
4955
4956 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
4957 if (w) {
4958 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
4959 if (r < 0)
4960 return r;
4961 }
4962
4963 w = json_variant_by_key(v, "tpm2_pubkey");
4964 if (w) {
4965 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
4966 if (r < 0)
4967 return log_debug_errno(r, "Failed to decode PCR public key.");
4968 } else if (pubkey_pcr_mask != 0)
4969 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4970
4971 w = json_variant_by_key(v, "tpm2_srk");
4972 if (w) {
4973 r = json_variant_unbase64(w, &srk_buf, &srk_buf_size);
4974 if (r < 0)
4975 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
4976 }
4977
4978 if (ret_keyslot)
4979 *ret_keyslot = keyslot;
4980 if (ret_hash_pcr_mask)
4981 *ret_hash_pcr_mask = hash_pcr_mask;
4982 if (ret_pcr_bank)
4983 *ret_pcr_bank = pcr_bank;
4984 if (ret_pubkey)
4985 *ret_pubkey = TAKE_PTR(pubkey);
4986 if (ret_pubkey_size)
4987 *ret_pubkey_size = pubkey_size;
4988 if (ret_pubkey_pcr_mask)
4989 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
4990 if (ret_primary_alg)
4991 *ret_primary_alg = primary_alg;
4992 if (ret_blob)
4993 *ret_blob = TAKE_PTR(blob);
4994 if (ret_blob_size)
4995 *ret_blob_size = blob_size;
4996 if (ret_policy_hash)
4997 *ret_policy_hash = TAKE_PTR(policy_hash);
4998 if (ret_policy_hash_size)
4999 *ret_policy_hash_size = policy_hash_size;
5000 if (ret_salt)
5001 *ret_salt = TAKE_PTR(salt);
5002 if (ret_salt_size)
5003 *ret_salt_size = salt_size;
5004 if (ret_flags)
5005 *ret_flags = flags;
5006 if (ret_srk_buf)
5007 *ret_srk_buf = TAKE_PTR(srk_buf);
5008 if (ret_srk_buf_size)
5009 *ret_srk_buf_size = srk_buf_size;
5010
5011 return 0;
5012 }
5013
5014 int tpm2_hash_alg_to_size(uint16_t alg) {
5015 switch (alg) {
5016 case TPM2_ALG_SHA1:
5017 return 20;
5018 case TPM2_ALG_SHA256:
5019 return 32;
5020 case TPM2_ALG_SHA384:
5021 return 48;
5022 case TPM2_ALG_SHA512:
5023 return 64;
5024 default:
5025 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm id 0x%" PRIx16, alg);
5026 }
5027 }
5028
5029 const char *tpm2_hash_alg_to_string(uint16_t alg) {
5030 switch (alg) {
5031 case TPM2_ALG_SHA1:
5032 return "sha1";
5033 case TPM2_ALG_SHA256:
5034 return "sha256";
5035 case TPM2_ALG_SHA384:
5036 return "sha384";
5037 case TPM2_ALG_SHA512:
5038 return "sha512";
5039 default:
5040 log_debug("Unknown hash algorithm id 0x%" PRIx16, alg);
5041 return NULL;
5042 }
5043 }
5044
5045 int tpm2_hash_alg_from_string(const char *alg) {
5046 if (strcaseeq_ptr(alg, "sha1"))
5047 return TPM2_ALG_SHA1;
5048 if (strcaseeq_ptr(alg, "sha256"))
5049 return TPM2_ALG_SHA256;
5050 if (strcaseeq_ptr(alg, "sha384"))
5051 return TPM2_ALG_SHA384;
5052 if (strcaseeq_ptr(alg, "sha512"))
5053 return TPM2_ALG_SHA512;
5054 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm name '%s'", alg);
5055 }
5056
5057 const char *tpm2_asym_alg_to_string(uint16_t alg) {
5058 switch (alg) {
5059 case TPM2_ALG_ECC:
5060 return "ecc";
5061 case TPM2_ALG_RSA:
5062 return "rsa";
5063 default:
5064 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16, alg);
5065 return NULL;
5066 }
5067 }
5068
5069 int tpm2_asym_alg_from_string(const char *alg) {
5070 if (strcaseeq_ptr(alg, "ecc"))
5071 return TPM2_ALG_ECC;
5072 if (strcaseeq_ptr(alg, "rsa"))
5073 return TPM2_ALG_RSA;
5074 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown asymmetric algorithm name '%s'", alg);
5075 }
5076
5077 Tpm2Support tpm2_support(void) {
5078 Tpm2Support support = TPM2_SUPPORT_NONE;
5079 int r;
5080
5081 if (detect_container() <= 0) {
5082 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
5083 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
5084 * let's assume containers never have a TPM, at least for now. */
5085
5086 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
5087 if (r < 0) {
5088 if (r != -ENOENT)
5089 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
5090 } else if (r == 0) /* populated! */
5091 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
5092 else
5093 /* If the directory exists but is empty, we know the subsystem is enabled but no
5094 * driver has been loaded yet. */
5095 support |= TPM2_SUPPORT_SUBSYSTEM;
5096 }
5097
5098 if (efi_has_tpm2())
5099 support |= TPM2_SUPPORT_FIRMWARE;
5100
5101 #if HAVE_TPM2
5102 support |= TPM2_SUPPORT_SYSTEM;
5103
5104 r = dlopen_tpm2();
5105 if (r >= 0)
5106 support |= TPM2_SUPPORT_LIBRARIES;
5107 #endif
5108
5109 return support;
5110 }
5111
5112 #if HAVE_TPM2
5113 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
5114 TPMI_ALG_HASH default_hash = 0;
5115 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
5116 if (v->hash != 0) {
5117 default_hash = v->hash;
5118 break;
5119 }
5120
5121 if (default_hash != 0)
5122 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
5123 if (v->hash == 0)
5124 v->hash = default_hash;
5125 }
5126 #endif
5127
5128 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
5129 * parse_*_argument() functions. */
5130
5131 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
5132 *
5133 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
5134 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
5135 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
5136 *
5137 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
5138 * tpm2_parse_pcr_argument_append(). */
5139 int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
5140 #if HAVE_TPM2
5141 int r;
5142
5143 assert(arg);
5144 assert(ret_pcr_values);
5145 assert(ret_n_pcr_values);
5146
5147 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
5148 size_t n_pcr_values = 0;
5149 r = tpm2_pcr_values_from_string(arg, &pcr_values, &n_pcr_values);
5150 if (r < 0)
5151 return log_error_errno(r, "Could not parse PCR values from '%s': %m", arg);
5152
5153 tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
5154
5155 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
5156
5157 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
5158 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
5159
5160 *ret_pcr_values = TAKE_PTR(pcr_values);
5161 *ret_n_pcr_values = n_pcr_values;
5162
5163 return 0;
5164 #else
5165 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
5166 #endif
5167 }
5168
5169 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
5170 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
5171 * must be correct.
5172 *
5173 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
5174 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
5175 * algorithm check applied again (in case either the previous or current array had no default hash
5176 * algorithm), and then the resulting array is sorted and rechecked for validity. */
5177 int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values) {
5178 #if HAVE_TPM2
5179 int r;
5180
5181 assert(arg);
5182 assert(pcr_values);
5183 assert(n_pcr_values);
5184
5185 _cleanup_free_ Tpm2PCRValue *more_pcr_values = NULL;
5186 size_t n_more_pcr_values;
5187 r = tpm2_parse_pcr_argument(arg, &more_pcr_values, &n_more_pcr_values);
5188 if (r < 0)
5189 return r;
5190
5191 /* If we got previous values, append them. */
5192 if (*pcr_values && !GREEDY_REALLOC_APPEND(more_pcr_values, n_more_pcr_values, *pcr_values, *n_pcr_values))
5193 return log_oom();
5194
5195 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values, n_more_pcr_values);
5196
5197 tpm2_sort_pcr_values(more_pcr_values, n_more_pcr_values);
5198
5199 if (!tpm2_pcr_values_valid(more_pcr_values, n_more_pcr_values))
5200 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
5201
5202 SWAP_TWO(*pcr_values, more_pcr_values);
5203 *n_pcr_values = n_more_pcr_values;
5204
5205 return 0;
5206 #else
5207 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
5208 #endif
5209 }
5210
5211 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
5212 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
5213 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
5214 * UINT32_MAX, and or-ing the mask otherwise. */
5215 int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *ret_mask) {
5216 #if HAVE_TPM2
5217 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
5218 size_t n_pcr_values;
5219 int r;
5220
5221 assert(arg);
5222 assert(ret_mask);
5223
5224 r = tpm2_parse_pcr_argument(arg, &pcr_values, &n_pcr_values);
5225 if (r < 0)
5226 return r;
5227
5228 if (n_pcr_values == 0) {
5229 /* This retains the previous behavior of clearing the mask if the arg is empty */
5230 *ret_mask = 0;
5231 return 0;
5232 }
5233
5234 size_t hash_count;
5235 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
5236 if (r < 0)
5237 return log_error_errno(r, "Could not get hash count from pcr values: %m");
5238
5239 if (hash_count > 1)
5240 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR hash banks selected.");
5241
5242 uint32_t new_mask;
5243 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
5244 if (r < 0)
5245 return log_error_errno(r, "Could not get pcr values mask: %m");
5246
5247 if (*ret_mask == UINT32_MAX)
5248 *ret_mask = new_mask;
5249 else
5250 *ret_mask |= new_mask;
5251
5252 return 0;
5253 #else
5254 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
5255 #endif
5256 }
5257
5258 int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
5259 _cleanup_strv_free_ char **search = NULL;
5260 _cleanup_free_ char *discovered_path = NULL;
5261 _cleanup_fclose_ FILE *f = NULL;
5262 int r;
5263
5264 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
5265 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5266
5267 search = strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
5268 if (!search)
5269 return log_oom_debug();
5270
5271 if (!path) {
5272 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
5273 * this case include /.extra/ in the search path, but only in this case, and if we run in the
5274 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
5275
5276 path = "tpm2-pcr-signature.json";
5277
5278 if (in_initrd())
5279 if (strv_extend(&search, "/.extra") < 0)
5280 return log_oom_debug();
5281 }
5282
5283 r = search_and_fopen(path, "re", NULL, (const char**) search, &f, &discovered_path);
5284 if (r < 0)
5285 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
5286
5287 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
5288 if (r < 0)
5289 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
5290
5291 return 0;
5292 }
5293
5294 int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
5295 _cleanup_free_ char *discovered_path = NULL;
5296 _cleanup_fclose_ FILE *f = NULL;
5297 int r;
5298
5299 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
5300 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
5301
5302 if (!path)
5303 path = "tpm2-pcr-public-key.pem";
5304
5305 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
5306 if (r < 0)
5307 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
5308
5309 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
5310 if (r < 0)
5311 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
5312
5313 return 0;
5314 }
5315
5316 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
5317
5318 /*
5319 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
5320 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
5321 * I found the wikipedia entry relevant and it contains links to
5322 * relevant RFCs:
5323 * - https://en.wikipedia.org/wiki/PBKDF2
5324 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
5325 */
5326 int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
5327 size_t passlen,
5328 const void *salt,
5329 size_t saltlen,
5330 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
5331
5332 uint8_t _cleanup_(erase_and_freep) *buffer = NULL;
5333 uint8_t u[SHA256_DIGEST_SIZE];
5334
5335 /* To keep this simple, since derived KeyLen (dkLen in docs)
5336 * Is the same as the hash output, we don't need multiple
5337 * blocks. Part of the algorithm is to add the block count
5338 * in, but this can be hardcoded to 1.
5339 */
5340 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
5341
5342 assert (salt);
5343 assert (saltlen > 0);
5344 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
5345 assert (passlen > 0);
5346
5347 /*
5348 * Build a buffer of salt + block_cnt and hmac_sha256 it we
5349 * do this as we don't have a context builder for HMAC_SHA256.
5350 */
5351 buffer = malloc(saltlen + sizeof(block_cnt));
5352 if (!buffer)
5353 return -ENOMEM;
5354
5355 memcpy(buffer, salt, saltlen);
5356 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
5357
5358 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
5359
5360 /* dk needs to be an unmodified u as u gets modified in the loop */
5361 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
5362 uint8_t *dk = ret_key;
5363
5364 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
5365 hmac_sha256(pass, passlen, u, sizeof(u), u);
5366
5367 for (size_t j=0; j < sizeof(u); j++)
5368 dk[j] ^= u[j];
5369 }
5370
5371 return 0;
5372 }
5373
5374 static const char* const tpm2_pcr_index_table[_TPM2_PCR_INDEX_MAX_DEFINED] = {
5375 [TPM2_PCR_PLATFORM_CODE] = "platform-code",
5376 [TPM2_PCR_PLATFORM_CONFIG] = "platform-config",
5377 [TPM2_PCR_EXTERNAL_CODE] = "external-code",
5378 [TPM2_PCR_EXTERNAL_CONFIG] = "external-config",
5379 [TPM2_PCR_BOOT_LOADER_CODE] = "boot-loader-code",
5380 [TPM2_PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
5381 [TPM2_PCR_HOST_PLATFORM] = "host-platform",
5382 [TPM2_PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
5383 [TPM2_PCR_KERNEL_INITRD] = "kernel-initrd",
5384 [TPM2_PCR_IMA] = "ima",
5385 [TPM2_PCR_KERNEL_BOOT] = "kernel-boot",
5386 [TPM2_PCR_KERNEL_CONFIG] = "kernel-config",
5387 [TPM2_PCR_SYSEXTS] = "sysexts",
5388 [TPM2_PCR_SHIM_POLICY] = "shim-policy",
5389 [TPM2_PCR_SYSTEM_IDENTITY] = "system-identity",
5390 [TPM2_PCR_DEBUG] = "debug",
5391 [TPM2_PCR_APPLICATION_SUPPORT] = "application-support",
5392 };
5393
5394 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index, int, TPM2_PCRS_MAX - 1);
5395 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index, int);