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