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