]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/tpm2-util.c
busctl: use json_variant_append_array()
[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"
d9b5841d 22#include "openssl-util.h"
fdf6c27c 23#include "parse-util.h"
5e521624 24#include "random-util.h"
2f5a892a 25#include "sha256.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
b57a7b3d
DS
139static inline void Esys_Freep(void *p) {
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
f4f5b3a9
DS
469static inline bool tpm2_supports_tpmt_public(Tpm2Context *c, const TPMT_PUBLIC *public) {
470 assert(c);
471 assert(public);
472
473 return tpm2_test_parms(c, public->type, &public->parameters);
474}
475
a47060bb
DS
476static inline bool tpm2_supports_tpmt_sym_def_object(Tpm2Context *c, const TPMT_SYM_DEF_OBJECT *parameters) {
477 assert(c);
478 assert(parameters);
479
480 TPMU_PUBLIC_PARMS parms = {
481 .symDetail.sym = *parameters,
482 };
483
484 return tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms);
485}
486
487static inline bool tpm2_supports_tpmt_sym_def(Tpm2Context *c, const TPMT_SYM_DEF *parameters) {
488 assert(c);
489 assert(parameters);
490
491 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
492 * functionally identical. */
493 TPMT_SYM_DEF_OBJECT object = {
494 .algorithm = parameters->algorithm,
495 .keyBits = parameters->keyBits,
496 .mode = parameters->mode,
497 };
498
499 return tpm2_supports_tpmt_sym_def_object(c, &object);
500}
501
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
1152static int tpm2_create_loaded(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handle *session, const TPMT_PUBLIC *template, const TPMS_SENSITIVE_CREATE *sensitive, TPM2B_PUBLIC **ret_public, TPM2B_PRIVATE **ret_private, Tpm2Handle **ret_handle);
1153
1154/* Get the SRK, creating one if needed. Returns 0 on success, or < 0 on error. */
1155static int tpm2_get_or_create_srk(
1156 Tpm2Context *c,
1157 const Tpm2Handle *session,
1158 TPM2B_PUBLIC **ret_public,
1159 TPM2B_NAME **ret_name,
1160 TPM2B_NAME **ret_qname,
1161 Tpm2Handle **ret_handle) {
1162
1163 int r;
1164
1165 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1166 if (r < 0)
1167 return r;
1168 if (r == 1)
1169 return 0;
1170
1171 /* No SRK, create and persist one */
1172 TPMT_PUBLIC template;
1173 r = tpm2_get_best_srk_template(c, &template);
1174 if (r < 0)
1175 return log_error_errno(r, "Could not get best SRK template: %m");
1176
1177 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
1178 r = tpm2_create_loaded(
1179 c,
1180 /* parent= */ NULL,
1181 session,
1182 &template,
1183 /* sensitive= */ NULL,
1184 /* ret_public= */ NULL,
1185 /* ret_private= */ NULL,
1186 &transient_handle);
1187 if (r < 0)
1188 return r;
1189
1190 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1191 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1192 * either case, all threads will get the persistent SRK below. */
1193 r = tpm2_persist_handle(c, transient_handle, session, TPM2_SRK_HANDLE, /* ret_persistent_handle= */ NULL);
1194 if (r < 0)
1195 return r;
1196
1197 /* The SRK should exist now. */
1198 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1199 if (r < 0)
1200 return r;
1201 if (r == 0)
1202 /* This should never happen. */
1203 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SRK we just persisted couldn't be found.");
1204
1205 return 0;
1206}
1207
c69bd0ab
DS
1208/* Utility functions for TPMS_PCR_SELECTION. */
1209
1210/* Convert a TPMS_PCR_SELECTION object to a mask. */
1211void tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s, uint32_t *ret) {
1212 assert(s);
1213 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
321a9d9e
LP
1214 assert(ret);
1215
c69bd0ab
DS
1216 uint32_t mask = 0;
1217 for (unsigned i = 0; i < s->sizeofSelect; i++)
1218 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
1219 *ret = mask;
1220}
321a9d9e 1221
c69bd0ab
DS
1222/* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1223void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
1224 assert(ret);
1225
1226 /* This is currently hardcoded at 24 PCRs, above. */
1227 if (!TPM2_PCR_MASK_VALID(mask))
1228 log_warning("PCR mask selections (%x) out of range, ignoring.",
1229 mask & ~((uint32_t)TPM2_PCRS_MASK));
1230
1231 *ret = (TPMS_PCR_SELECTION){
1232 .hash = hash_alg,
1233 .sizeofSelect = TPM2_PCRS_MAX / 8,
1234 .pcrSelect[0] = mask & 0xff,
1235 .pcrSelect[1] = (mask >> 8) & 0xff,
1236 .pcrSelect[2] = (mask >> 16) & 0xff,
1237 };
1238}
1239
1240/* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1241void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1242 assert(a);
1243 assert(b);
1244 assert(a->hash == b->hash);
1245
1246 uint32_t maska, maskb;
1247 tpm2_tpms_pcr_selection_to_mask(a, &maska);
1248 tpm2_tpms_pcr_selection_to_mask(b, &maskb);
1249 tpm2_tpms_pcr_selection_from_mask(maska | maskb, a->hash, a);
1250}
1251
1252/* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1253void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1254 assert(a);
1255 assert(b);
1256 assert(a->hash == b->hash);
1257
1258 uint32_t maska, maskb;
1259 tpm2_tpms_pcr_selection_to_mask(a, &maska);
1260 tpm2_tpms_pcr_selection_to_mask(b, &maskb);
1261 tpm2_tpms_pcr_selection_from_mask(maska & ~maskb, a->hash, a);
1262}
1263
1264/* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1265void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
1266 if (a == b)
1267 return;
1268
1269 tpm2_tpms_pcr_selection_add(a, b);
1270 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
1271}
1272
1273#define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1274 _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, UNIQ)
1275#define _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, uniq) \
1276 FOREACH_PCR_IN_MASK(pcr, \
1277 ({ uint32_t UNIQ_T(_mask, uniq); \
1278 tpm2_tpms_pcr_selection_to_mask(tpms, &UNIQ_T(_mask, uniq)); \
1279 UNIQ_T(_mask, uniq); \
1280 }))
1281
1282#define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1283 UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ)
1284#define UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, uniq) \
1285 for (TPML_PCR_SELECTION *UNIQ_T(_tpml, uniq) = (TPML_PCR_SELECTION*)(tpml); \
1286 UNIQ_T(_tpml, uniq); UNIQ_T(_tpml, uniq) = NULL) \
1287 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, UNIQ_T(_tpml, uniq))
1288#define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1289 for (TPMS_PCR_SELECTION *tpms = tpml->pcrSelections; \
1290 (uint32_t)(tpms - tpml->pcrSelections) < tpml->count; \
1291 tpms++)
1292
1293#define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1294 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1295 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1296
1297char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
1298 assert(s);
1299
1300 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
1301
1302 uint32_t mask;
1303 tpm2_tpms_pcr_selection_to_mask(s, &mask);
1304 _cleanup_free_ char *maskstr = tpm2_pcr_mask_to_string(mask);
1305 if (!maskstr)
1306 return NULL;
1307
1308 return strjoin(algstr, "(", maskstr, ")");
1309}
1310
1311size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
1312 assert(s);
1313
1314 uint32_t mask;
1315 tpm2_tpms_pcr_selection_to_mask(s, &mask);
a12bc99e 1316 return popcount(mask);
c69bd0ab
DS
1317}
1318
1319/* Utility functions for TPML_PCR_SELECTION. */
1320
1321/* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1322static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
1323 assert(l);
1324 assert(l->count <= sizeof(l->pcrSelections));
1325 assert(index < l->count);
1326
1327 size_t s = l->count - (index + 1);
1328 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
1329 l->count--;
1330}
1331
1332/* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1333 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1334 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1335static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1336 TPML_PCR_SELECTION *l,
1337 TPMI_ALG_HASH hash_alg) {
1338
1339 assert(l);
1340
1341 TPMS_PCR_SELECTION *selection = NULL;
1342 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1343 if (s->hash == hash_alg) {
1344 selection = s;
1345 break;
1346 }
1347
1348 if (!selection)
1349 return NULL;
1350
1351 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1352 for (uint32_t i = l->count - 1; i > 0; i--) {
1353 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
1354
1355 if (selection == s)
1356 break;
1357
1358 if (s->hash == hash_alg) {
1359 tpm2_tpms_pcr_selection_move(selection, s);
1360 tpm2_tpml_pcr_selection_remove_index(l, i);
4dde902e 1361 }
c69bd0ab
DS
1362 }
1363
1364 return selection;
1365}
1366
1367/* Convert a TPML_PCR_SELECTION object to a mask. Returns -ENOENT if 'hash_alg' is not in the object. */
1368int tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg, uint32_t *ret) {
1369 assert(l);
1370 assert(ret);
1371
1372 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1373 * are multiple entries with the requested hash alg. */
1374 TPML_PCR_SELECTION lcopy = *l;
1375
1376 TPMS_PCR_SELECTION *s;
1377 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
1378 if (!s)
1379 return SYNTHETIC_ERRNO(ENOENT);
1380
1381 tpm2_tpms_pcr_selection_to_mask(s, ret);
1382 return 0;
1383}
1384
1385/* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1386void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
1387 assert(ret);
1388
1389 TPMS_PCR_SELECTION s;
1390 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
1391
1392 *ret = (TPML_PCR_SELECTION){
1393 .count = 1,
1394 .pcrSelections[0] = s,
321a9d9e
LP
1395 };
1396}
1397
c69bd0ab
DS
1398/* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1399static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
1400 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1401 /* This removes all duplicates for s->hash. */
1402 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1403}
1404
1405/* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1406 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1407 * entries with the same hash alg. */
1408void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1409 assert(l);
1410 assert(s);
1411
1412 if (tpm2_tpms_pcr_selection_is_empty(s))
1413 return;
1414
1415 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1416 if (selection) {
1417 tpm2_tpms_pcr_selection_add(selection, s);
1418 return;
1419 }
1420
1421 /* It's already broken if the count is higher than the array has size for. */
1422 assert(!(l->count > sizeof(l->pcrSelections)));
1423
1424 /* If full, the cleanup should result in at least one available entry. */
1425 if (l->count == sizeof(l->pcrSelections))
1426 tpm2_tpml_pcr_selection_cleanup(l);
1427
1428 assert(l->count < sizeof(l->pcrSelections));
1429 l->pcrSelections[l->count++] = *s;
1430}
1431
1432/* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1433 * will combine all entries for 's->hash' in 'l'. */
1434void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1435 assert(l);
1436 assert(s);
1437
1438 if (tpm2_tpms_pcr_selection_is_empty(s))
1439 return;
1440
1441 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1442 if (selection)
1443 tpm2_tpms_pcr_selection_sub(selection, s);
1444}
1445
1446/* Add all PCR selections in 'b' to 'a'. */
1447void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1448 assert(a);
1449 assert(b);
1450
1451 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
1452 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
1453}
1454
1455/* Remove all PCR selections in 'b' from 'a'. */
1456void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1457 assert(a);
1458 assert(b);
1459
1460 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
1461 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
1462}
1463
1464char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
1465 assert(l);
1466
1467 _cleanup_free_ char *banks = NULL;
1468 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, (TPML_PCR_SELECTION*) l) {
1469 if (tpm2_tpms_pcr_selection_is_empty(s))
1470 continue;
1471
1472 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
1473 if (!str || !strextend_with_separator(&banks, ",", str))
1474 return NULL;
1475 }
1476
1477 return strjoin("[", strempty(banks), "]");
1478}
1479
1480size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
1481 assert(l);
1482 assert(l->count <= sizeof(l->pcrSelections));
1483
1484 size_t weight = 0;
1485 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1486 size_t w = tpm2_tpms_pcr_selection_weight(s);
1487 assert(weight <= SIZE_MAX - w);
1488 weight += w;
1489 }
1490
1491 return weight;
1492}
1493
c57d8bc8
DS
1494static void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
1495 if (!DEBUG_LOGGING || !l)
1496 return;
1497
1498 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
1499 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
1500}
1501
23b972d5
DS
1502static void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
1503 if (!DEBUG_LOGGING || !buffer || size == 0)
1504 return;
1505
1506 _cleanup_free_ char *h = hexmem(buffer, size);
1507 log_debug("%s: %s", msg ?: "Buffer", strna(h));
1508}
1509
1510static void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
1511 if (digest)
1512 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
1513}
1514
dbae4b95
DS
1515static void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
1516 if (name)
1517 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
1518}
1519
23b972d5
DS
1520static int tpm2_get_policy_digest(
1521 Tpm2Context *c,
1522 const Tpm2Handle *session,
1523 TPM2B_DIGEST **ret_policy_digest) {
1524
1525 TSS2_RC rc;
1526
1527 if (!DEBUG_LOGGING && !ret_policy_digest)
1528 return 0;
1529
1530 assert(c);
1531 assert(session);
1532
1533 log_debug("Acquiring policy digest.");
1534
1535 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1536 rc = sym_Esys_PolicyGetDigest(
1537 c->esys_context,
1538 session->esys_handle,
1539 ESYS_TR_NONE,
1540 ESYS_TR_NONE,
1541 ESYS_TR_NONE,
1542 &policy_digest);
1543 if (rc != TSS2_RC_SUCCESS)
1544 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1545 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1546
1547 tpm2_log_debug_digest(policy_digest, "Session policy digest");
1548
1549 if (ret_policy_digest)
1550 *ret_policy_digest = TAKE_PTR(policy_digest);
1551
1552 return 0;
1553}
1554
e3f1f210
DS
1555static int tpm2_create(
1556 Tpm2Context *c,
1557 const Tpm2Handle *parent,
1558 const Tpm2Handle *session,
1559 const TPMT_PUBLIC *template,
1560 const TPMS_SENSITIVE_CREATE *sensitive,
1561 TPM2B_PUBLIC **ret_public,
1562 TPM2B_PRIVATE **ret_private) {
1563
1564 usec_t ts;
1565 TSS2_RC rc;
1566
1567 assert(c);
1568 assert(template);
1569
1570 log_debug("Creating object on TPM.");
1571
1572 ts = now(CLOCK_MONOTONIC);
1573
1574 TPM2B_PUBLIC tpm2b_public = {
1575 .size = sizeof(*template) - sizeof(template->unique),
1576 .publicArea = *template,
1577 };
1578
1579 /* Zero the unique area. */
1580 zero(tpm2b_public.publicArea.unique);
1581
1582 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
1583 if (sensitive)
1584 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
1585 .size = sizeof(*sensitive),
1586 .sensitive = *sensitive,
1587 };
1588 else
1589 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
1590
1591 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1592 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
1593 rc = sym_Esys_Create(
1594 c->esys_context,
1595 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
1596 session ? session->esys_handle : ESYS_TR_PASSWORD,
1597 ESYS_TR_NONE,
1598 ESYS_TR_NONE,
1599 &tpm2b_sensitive,
1600 &tpm2b_public,
1601 /* outsideInfo= */ NULL,
1602 &(TPML_PCR_SELECTION) {},
1603 &private,
1604 &public,
1605 /* creationData= */ NULL,
1606 /* creationHash= */ NULL,
1607 /* creationTicket= */ NULL);
1608 if (rc != TSS2_RC_SUCCESS)
1609 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1610 "Failed to generate object in TPM: %s",
1611 sym_Tss2_RC_Decode(rc));
1612
1613 log_debug("Successfully created object on TPM in %s.",
1614 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
1615
1616 if (ret_public)
1617 *ret_public = TAKE_PTR(public);
1618 if (ret_private)
1619 *ret_private = TAKE_PTR(private);
1620
1621 return 0;
1622}
1623
d1d0de73
DS
1624static int tpm2_load(
1625 Tpm2Context *c,
1626 const Tpm2Handle *parent,
1627 const Tpm2Handle *session,
1628 const TPM2B_PUBLIC *public,
1629 const TPM2B_PRIVATE *private,
1630 Tpm2Handle **ret_handle) {
1631
1632 TSS2_RC rc;
1633 int r;
1634
1635 assert(c);
1636 assert(public);
1637 assert(private);
1638 assert(ret_handle);
1639
1640 log_debug("Loading object into TPM.");
1641
1642 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1643 r = tpm2_handle_new(c, &handle);
1644 if (r < 0)
1645 return r;
1646
1647 rc = sym_Esys_Load(
1648 c->esys_context,
1649 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
1650 session ? session->esys_handle : ESYS_TR_PASSWORD,
1651 ESYS_TR_NONE,
1652 ESYS_TR_NONE,
1653 private,
1654 public,
1655 &handle->esys_handle);
1656 if (rc == TPM2_RC_LOCKOUT)
1657 return log_error_errno(SYNTHETIC_ERRNO(ENOLCK),
1658 "TPM2 device is in dictionary attack lockout mode.");
1659 if (rc != TSS2_RC_SUCCESS)
1660 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1661 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc));
1662
1663 *ret_handle = TAKE_PTR(handle);
1664
1665 return 0;
1666}
1667
efe153bd
DS
1668static int tpm2_load_external(
1669 Tpm2Context *c,
1670 const Tpm2Handle *session,
1671 const TPM2B_PUBLIC *public,
1672 const TPM2B_SENSITIVE *private,
1673 Tpm2Handle **ret_handle) {
1674
1675 TSS2_RC rc;
1676 int r;
1677
1678 assert(c);
1679 assert(ret_handle);
1680
1681 log_debug("Loading external key into TPM.");
1682
1683 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1684 r = tpm2_handle_new(c, &handle);
1685 if (r < 0)
1686 return r;
1687
1688 rc = sym_Esys_LoadExternal(
1689 c->esys_context,
1690 session ? session->esys_handle : ESYS_TR_NONE,
1691 ESYS_TR_NONE,
1692 ESYS_TR_NONE,
1693 private,
1694 public,
1695#if HAVE_TSS2_ESYS3
1696 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
1697 * hierarchy, older versions need TPM2_RH_* instead. */
1698 ESYS_TR_RH_OWNER,
1699#else
1700 TPM2_RH_OWNER,
1701#endif
1702 &handle->esys_handle);
1703 if (rc != TSS2_RC_SUCCESS)
1704 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1705 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
1706
1707 *ret_handle = TAKE_PTR(handle);
1708
1709 return 0;
1710}
1711
cea525a9
DS
1712/* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
1713 * use tpm2_create_loaded(). */
1714static int _tpm2_create_loaded(
1715 Tpm2Context *c,
1716 const Tpm2Handle *parent,
1717 const Tpm2Handle *session,
1718 const TPMT_PUBLIC *template,
1719 const TPMS_SENSITIVE_CREATE *sensitive,
1720 TPM2B_PUBLIC **ret_public,
1721 TPM2B_PRIVATE **ret_private,
1722 Tpm2Handle **ret_handle) {
1723
1724 usec_t ts;
1725 TSS2_RC rc;
1726 int r;
1727
1728 assert(c);
1729 assert(template);
1730
1731 log_debug("Creating loaded object on TPM.");
1732
1733 ts = now(CLOCK_MONOTONIC);
1734
1735 /* Copy the input template and zero the unique area. */
1736 TPMT_PUBLIC template_copy = *template;
1737 zero(template_copy.unique);
1738
1739 TPM2B_TEMPLATE tpm2b_template;
1740 size_t size = 0;
1741 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(
1742 &template_copy,
1743 tpm2b_template.buffer,
1744 sizeof(tpm2b_template.buffer),
1745 &size);
1746 if (rc != TSS2_RC_SUCCESS)
1747 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1748 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc));
1749 assert(size <= UINT16_MAX);
1750 tpm2b_template.size = size;
1751
1752 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
1753 if (sensitive)
1754 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
1755 .size = sizeof(*sensitive),
1756 .sensitive = *sensitive,
1757 };
1758 else
1759 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
1760
1761 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1762 r = tpm2_handle_new(c, &handle);
1763 if (r < 0)
1764 return r;
1765
1766 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1767 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
1768 rc = sym_Esys_CreateLoaded(
1769 c->esys_context,
1770 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
1771 session ? session->esys_handle : ESYS_TR_PASSWORD,
1772 ESYS_TR_NONE,
1773 ESYS_TR_NONE,
1774 &tpm2b_sensitive,
1775 &tpm2b_template,
1776 &handle->esys_handle,
1777 &private,
1778 &public);
1779 if (rc != TSS2_RC_SUCCESS)
1780 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1781 "Failed to generate loaded object in TPM: %s",
1782 sym_Tss2_RC_Decode(rc));
1783
1784 log_debug("Successfully created loaded object on TPM in %s.",
1785 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
1786
1787 if (ret_public)
1788 *ret_public = TAKE_PTR(public);
1789 if (ret_private)
1790 *ret_private = TAKE_PTR(private);
1791 if (ret_handle)
1792 *ret_handle = TAKE_PTR(handle);
1793
1794 return 0;
1795}
1796
1797/* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
1798 * separately. */
1799static int tpm2_create_loaded(
1800 Tpm2Context *c,
1801 const Tpm2Handle *parent,
1802 const Tpm2Handle *session,
1803 const TPMT_PUBLIC *template,
1804 const TPMS_SENSITIVE_CREATE *sensitive,
1805 TPM2B_PUBLIC **ret_public,
1806 TPM2B_PRIVATE **ret_private,
1807 Tpm2Handle **ret_handle) {
1808
1809 int r;
1810
1811 if (tpm2_supports_command(c, TPM2_CC_CreateLoaded))
1812 return _tpm2_create_loaded(c, parent, session, template, sensitive, ret_public, ret_private, ret_handle);
1813
1814 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
1815 * create and load manually. */
1816 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1817 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
1818 r = tpm2_create(c, parent, session, template, sensitive, &public, &private);
1819 if (r < 0)
1820 return r;
1821
1822 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1823 r = tpm2_load(c, parent, session, public, private, &handle);
1824 if (r < 0)
1825 return r;
1826
1827 if (ret_public)
1828 *ret_public = TAKE_PTR(public);
1829 if (ret_private)
1830 *ret_private = TAKE_PTR(private);
1831 if (ret_handle)
1832 *ret_handle = TAKE_PTR(handle);
1833
1834 return 0;
1835}
1836
c57d8bc8
DS
1837static int tpm2_pcr_read(
1838 Tpm2Context *c,
1839 const TPML_PCR_SELECTION *pcr_selection,
1840 TPML_PCR_SELECTION *ret_pcr_selection,
1841 TPM2B_DIGEST **ret_pcr_values,
c648a4b8 1842 size_t *ret_n_pcr_values) {
c57d8bc8
DS
1843
1844 _cleanup_free_ TPM2B_DIGEST *pcr_values = NULL;
1845 TPML_PCR_SELECTION remaining, total_read = {};
c648a4b8 1846 size_t n_pcr_values = 0;
c57d8bc8 1847 TSS2_RC rc;
321a9d9e 1848
c57d8bc8
DS
1849 assert(c);
1850 assert(pcr_selection);
321a9d9e 1851
c57d8bc8
DS
1852 remaining = *pcr_selection;
1853 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
1854 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
1855 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
321a9d9e 1856
c57d8bc8 1857 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
321a9d9e 1858
c57d8bc8
DS
1859 /* Unfortunately, PCR_Read will not return more than 8 values. */
1860 rc = sym_Esys_PCR_Read(
1861 c->esys_context,
1862 ESYS_TR_NONE,
1863 ESYS_TR_NONE,
1864 ESYS_TR_NONE,
1865 &remaining,
1866 NULL,
1867 &current_read,
1868 &current_values);
1869 if (rc != TSS2_RC_SUCCESS)
1870 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1871 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
321a9d9e 1872
c57d8bc8
DS
1873 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
1874 log_warning("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
1875 break;
321a9d9e
LP
1876 }
1877
c57d8bc8
DS
1878 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
1879 tpm2_tpml_pcr_selection_add(&total_read, current_read);
1880
c648a4b8 1881 if (!GREEDY_REALLOC(pcr_values, n_pcr_values + current_values->count))
c57d8bc8
DS
1882 return log_oom();
1883
c648a4b8 1884 memcpy_safe(&pcr_values[n_pcr_values], current_values->digests,
c57d8bc8 1885 current_values->count * sizeof(TPM2B_DIGEST));
c648a4b8 1886 n_pcr_values += current_values->count;
c57d8bc8
DS
1887
1888 if (DEBUG_LOGGING) {
1889 unsigned i = 0;
1890 FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, s, current_read) {
1891 assert(i < current_values->count);
1892
1893 TPM2B_DIGEST *d = &current_values->digests[i];
1894 i++;
1895
1896 TPML_PCR_SELECTION l;
1897 tpm2_tpml_pcr_selection_from_mask(INDEX_TO_MASK(uint32_t, pcr), s->hash, &l);
1898
1899 _cleanup_free_ char *desc = tpm2_tpml_pcr_selection_to_string(&l);
1900 tpm2_log_debug_digest(d, strna(desc));
1901 }
1902 }
321a9d9e
LP
1903 }
1904
c57d8bc8
DS
1905 if (ret_pcr_selection)
1906 *ret_pcr_selection = total_read;
1907 if (ret_pcr_values)
1908 *ret_pcr_values = TAKE_PTR(pcr_values);
c648a4b8
DS
1909 if (ret_n_pcr_values)
1910 *ret_n_pcr_values = n_pcr_values;
c57d8bc8
DS
1911
1912 return 0;
321a9d9e
LP
1913}
1914
1915static int tpm2_pcr_mask_good(
23e9ccc2 1916 Tpm2Context *c,
321a9d9e
LP
1917 TPMI_ALG_HASH bank,
1918 uint32_t mask) {
1919
c57d8bc8 1920 _cleanup_free_ TPM2B_DIGEST *pcr_values = NULL;
321a9d9e 1921 TPML_PCR_SELECTION selection;
c648a4b8 1922 size_t n_pcr_values = 0;
c57d8bc8 1923 int r;
321a9d9e
LP
1924
1925 assert(c);
1926
1927 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
1928 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
1929 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
1930
c69bd0ab 1931 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
321a9d9e 1932
c648a4b8 1933 r = tpm2_pcr_read(c, &selection, &selection, &pcr_values, &n_pcr_values);
c57d8bc8
DS
1934 if (r < 0)
1935 return r;
321a9d9e
LP
1936
1937 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
c57d8bc8
DS
1938 unsigned i = 0;
1939 FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, s, &selection) {
c648a4b8 1940 assert(i < n_pcr_values);
321a9d9e 1941
c57d8bc8
DS
1942 if (!memeqbyte(0x00, pcr_values[i].buffer, pcr_values[i].size) &&
1943 !memeqbyte(0xFF, pcr_values[i].buffer, pcr_values[i].size))
1944 return true;
321a9d9e 1945
c57d8bc8 1946 i++;
321a9d9e
LP
1947 }
1948
c57d8bc8 1949 return false;
321a9d9e
LP
1950}
1951
59fafaee
LP
1952static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
1953
1954 assert(selection);
1955
1956 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
1957 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
1958 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
1959 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
7bfe0a48 1960 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
1961 return false;
1962 }
1963
1964 assert_cc(TPM2_PCRS_MAX % 8 == 0);
1965
1966 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
1967 * enabled for this bank. Otherwise this TPM doesn't qualify. */
1968 bool valid = true;
1969 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
1970 if (selection->pcrSelect[j] != 0xFF) {
1971 valid = false;
1972 break;
1973 }
1974
1975 if (!valid)
1976 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
7bfe0a48 1977 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
1978
1979 return valid;
1980}
1981
07697bfe 1982static int tpm2_get_best_pcr_bank(
23e9ccc2 1983 Tpm2Context *c,
321a9d9e 1984 uint32_t pcr_mask,
07697bfe
LP
1985 TPMI_ALG_HASH *ret) {
1986
321a9d9e 1987 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
59fafaee 1988 int r;
07697bfe 1989
321a9d9e 1990 assert(c);
3a35d6cd 1991 assert(ret);
321a9d9e 1992
9ea0ffe6 1993 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
3a35d6cd 1994 TPMI_ALG_HASH hash = selection->hash;
321a9d9e
LP
1995 int good;
1996
1997 /* For now we are only interested in the SHA1 and SHA256 banks */
3a35d6cd 1998 if (!IN_SET(hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
321a9d9e 1999 continue;
07697bfe 2000
3a35d6cd 2001 r = tpm2_bank_has24(selection);
59fafaee
LP
2002 if (r < 0)
2003 return r;
2004 if (!r)
07697bfe 2005 continue;
07697bfe 2006
3a35d6cd 2007 good = tpm2_pcr_mask_good(c, hash, pcr_mask);
321a9d9e
LP
2008 if (good < 0)
2009 return good;
2010
3a35d6cd 2011 if (hash == TPM2_ALG_SHA256) {
321a9d9e
LP
2012 supported_hash = TPM2_ALG_SHA256;
2013 if (good) {
2014 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2015 hash_with_valid_pcr = TPM2_ALG_SHA256;
2016 break;
2017 }
2018 } else {
3a35d6cd 2019 assert(hash == TPM2_ALG_SHA1);
321a9d9e
LP
2020
2021 if (supported_hash == 0)
2022 supported_hash = TPM2_ALG_SHA1;
07697bfe 2023
321a9d9e
LP
2024 if (good && hash_with_valid_pcr == 0)
2025 hash_with_valid_pcr = TPM2_ALG_SHA1;
2026 }
07697bfe
LP
2027 }
2028
321a9d9e
LP
2029 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2030 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2031 * SHA1.
2032 *
2033 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2034 * not initialized. */
2035
2036 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
2037 assert(supported_hash == TPM2_ALG_SHA256);
2038 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2039 *ret = TPM2_ALG_SHA256;
2040 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
2041 if (supported_hash == TPM2_ALG_SHA256)
2042 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.");
2043 else {
2044 assert(supported_hash == TPM2_ALG_SHA1);
2045 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.");
2046 }
2047
2048 *ret = TPM2_ALG_SHA1;
2049 } else if (supported_hash == TPM2_ALG_SHA256) {
2050 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!");
2051 *ret = TPM2_ALG_SHA256;
2052 } else if (supported_hash == TPM2_ALG_SHA1) {
2053 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!");
2054 *ret = TPM2_ALG_SHA1;
2055 } else
07697bfe
LP
2056 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2057 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2058
07697bfe
LP
2059 return 0;
2060}
2061
c5bf1f85 2062int tpm2_get_good_pcr_banks(
23e9ccc2 2063 Tpm2Context *c,
c5bf1f85
LP
2064 uint32_t pcr_mask,
2065 TPMI_ALG_HASH **ret) {
2066
2067 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
c5bf1f85 2068 size_t n_good_banks = 0, n_fallback_banks = 0;
c5bf1f85
LP
2069 int r;
2070
2071 assert(c);
2072 assert(ret);
2073
9ea0ffe6 2074 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
3a35d6cd 2075 TPMI_ALG_HASH hash = selection->hash;
c5bf1f85
LP
2076
2077 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
3a35d6cd 2078 r = tpm2_bank_has24(selection);
c5bf1f85
LP
2079 if (r < 0)
2080 return r;
2081 if (!r)
2082 continue;
2083
2084 /* Let's now see if this bank has any of the selected PCRs actually initialized */
3a35d6cd 2085 r = tpm2_pcr_mask_good(c, hash, pcr_mask);
c5bf1f85
LP
2086 if (r < 0)
2087 return r;
2088
2089 if (n_good_banks + n_fallback_banks >= INT_MAX)
2090 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
2091
2092 if (r) {
2093 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
2094 return log_oom();
2095
3a35d6cd 2096 good_banks[n_good_banks++] = hash;
c5bf1f85
LP
2097 } else {
2098 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
2099 return log_oom();
2100
3a35d6cd 2101 fallback_banks[n_fallback_banks++] = hash;
c5bf1f85
LP
2102 }
2103 }
2104
2105 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2106 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2107 if (n_good_banks > 0) {
2108 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
2109 *ret = TAKE_PTR(good_banks);
2110 return (int) n_good_banks;
2111 }
2112 if (n_fallback_banks > 0) {
2113 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
2114 *ret = TAKE_PTR(fallback_banks);
2115 return (int) n_fallback_banks;
2116 }
2117
2118 /* No suitable banks found. */
2119 *ret = NULL;
2120 return 0;
2121}
2122
e4481cc5 2123int tpm2_get_good_pcr_banks_strv(
23e9ccc2 2124 Tpm2Context *c,
e4481cc5
LP
2125 uint32_t pcr_mask,
2126 char ***ret) {
2127
0d7009d3 2128#if HAVE_OPENSSL
e4481cc5
LP
2129 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
2130 _cleanup_strv_free_ char **l = NULL;
2131 int n_algs;
2132
2133 assert(c);
2134 assert(ret);
2135
2136 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
2137 if (n_algs < 0)
2138 return n_algs;
2139
2140 for (int i = 0; i < n_algs; i++) {
2141 _cleanup_free_ char *n = NULL;
2142 const EVP_MD *implementation;
2143 const char *salg;
2144
7bfe0a48 2145 salg = tpm2_hash_alg_to_string(algs[i]);
e4481cc5
LP
2146 if (!salg)
2147 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
2148
2149 implementation = EVP_get_digestbyname(salg);
2150 if (!implementation)
2151 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2152
2153 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
2154 if (!n)
2155 return log_oom();
2156
2157 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2158
2159 if (strv_consume(&l, TAKE_PTR(n)) < 0)
2160 return log_oom();
2161 }
2162
2163 *ret = TAKE_PTR(l);
2164 return 0;
0d7009d3
DS
2165#else /* HAVE_OPENSSL */
2166 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2167#endif
e4481cc5
LP
2168}
2169
da92d39a
DS
2170/* Hash data into the digest.
2171 *
2172 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2173 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2174 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2175 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2176 *
2177 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2178 * correct for 'alg'.
2179 *
2180 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2181int tpm2_digest_many(
2182 TPMI_ALG_HASH alg,
2183 TPM2B_DIGEST *digest,
2184 const struct iovec data[],
2185 size_t n_data,
2186 bool extend) {
2187
2188 struct sha256_ctx ctx;
2189
2190 assert(digest);
2191 assert(data || n_data == 0);
2192
2193 if (alg != TPM2_ALG_SHA256)
2194 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2195 "Hash algorithm not supported: 0x%x", alg);
2196
2197 if (extend && digest->size != SHA256_DIGEST_SIZE)
2198 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2199 "Digest size 0x%x, require 0x%x",
2200 digest->size, (unsigned)SHA256_DIGEST_SIZE);
2201
2202 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2203 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
2204
2205 CLEANUP_ERASE(ctx);
2206
2207 sha256_init_ctx(&ctx);
2208
2209 if (extend)
2210 sha256_process_bytes(digest->buffer, digest->size, &ctx);
2211 else {
2212 *digest = (TPM2B_DIGEST){ .size = SHA256_DIGEST_SIZE, };
2213 if (n_data == 0) /* If not extending and no data, return zero hash */
2214 return 0;
2215 }
2216
2217 for (size_t i = 0; i < n_data; i++)
2218 sha256_process_bytes(data[i].iov_base, data[i].iov_len, &ctx);
2219
2220 sha256_finish_ctx(&ctx, digest->buffer);
2221
2222 return 0;
2223}
2224
2225/* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2226int tpm2_digest_many_digests(
2227 TPMI_ALG_HASH alg,
2228 TPM2B_DIGEST *digest,
2229 const TPM2B_DIGEST data[],
2230 size_t n_data,
2231 bool extend) {
2232
2233 _cleanup_free_ struct iovec *iovecs = NULL;
2234
2235 assert(data || n_data == 0);
2236
2237 iovecs = new(struct iovec, n_data);
2238 if (!iovecs)
2239 return log_oom();
2240
2241 for (size_t i = 0; i < n_data; i++)
2242 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
2243
2244 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
2245}
2246
409a65f8
DS
2247static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
2248 TPM2B_AUTH auth = {};
2249 TSS2_RC rc;
2250 int r;
2251
2252 assert(c);
2253 assert(handle);
2254
2255 if (!pin)
2256 return 0;
2257
2258 CLEANUP_ERASE(auth);
2259
2260 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &auth, pin, strlen(pin), /* extend= */ false);
2261 if (r < 0)
2262 return r;
2263
2264 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, &auth);
2265 if (rc != TSS2_RC_SUCCESS)
2266 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2267 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
2268
2269 return 0;
2270}
2271
e976445d
DS
2272static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
2273 TPMA_SESSION flags = 0;
2274 TSS2_RC rc;
2275
2276 assert(c);
2277 assert(session);
2278
2279 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
2280 if (rc != TSS2_RC_SUCCESS)
2281 return false;
2282
2283 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
2284}
2285
da29de23 2286static int tpm2_make_encryption_session(
23e9ccc2 2287 Tpm2Context *c,
16e16b8c
DS
2288 const Tpm2Handle *primary,
2289 const Tpm2Handle *bind_key,
16e16b8c 2290 Tpm2Handle **ret_session) {
da29de23 2291
da29de23
GG
2292 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
2293 TPMA_SESSION_CONTINUESESSION;
da29de23 2294 TSS2_RC rc;
16e16b8c 2295 int r;
da29de23
GG
2296
2297 assert(c);
16e16b8c 2298 assert(ret_session);
da29de23
GG
2299
2300 log_debug("Starting HMAC encryption session.");
2301
2302 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2303 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2304 * recover the salt, which is then used for key derivation. */
1dc8f518 2305 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
16e16b8c
DS
2306 r = tpm2_handle_new(c, &session);
2307 if (r < 0)
2308 return r;
2309
da29de23 2310 rc = sym_Esys_StartAuthSession(
23e9ccc2 2311 c->esys_context,
16e16b8c
DS
2312 primary->esys_handle,
2313 bind_key->esys_handle,
da29de23
GG
2314 ESYS_TR_NONE,
2315 ESYS_TR_NONE,
2316 ESYS_TR_NONE,
2317 NULL,
2318 TPM2_SE_HMAC,
a47060bb 2319 &SESSION_TEMPLATE_SYM_AES_128_CFB,
da29de23 2320 TPM2_ALG_SHA256,
16e16b8c 2321 &session->esys_handle);
da29de23
GG
2322 if (rc != TSS2_RC_SUCCESS)
2323 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2324 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2325
2326 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2327 * always used for sessions), this provides confidentiality, integrity and replay protection for
2328 * operations that use this session. */
16e16b8c 2329 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
da29de23
GG
2330 if (rc != TSS2_RC_SUCCESS)
2331 return log_error_errno(
2332 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2333 "Failed to configure TPM session: %s",
2334 sym_Tss2_RC_Decode(rc));
2335
16e16b8c 2336 *ret_session = TAKE_PTR(session);
da29de23 2337
da29de23
GG
2338 return 0;
2339}
2340
2cd9d575
DS
2341static int tpm2_make_policy_session(
2342 Tpm2Context *c,
2343 const Tpm2Handle *primary,
2344 const Tpm2Handle *encryption_session,
2345 bool trial,
2346 Tpm2Handle **ret_session) {
2347
2cd9d575
DS
2348 TPM2_SE session_type = trial ? TPM2_SE_TRIAL : TPM2_SE_POLICY;
2349 TSS2_RC rc;
2350 int r;
2351
2352 assert(c);
2353 assert(primary);
2354 assert(encryption_session);
2355 assert(ret_session);
2356
2357 if (!tpm2_is_encryption_session(c, encryption_session))
2358 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2359 "Missing encryption session");
2360
2361 log_debug("Starting policy session.");
2362
1dc8f518 2363 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
2cd9d575
DS
2364 r = tpm2_handle_new(c, &session);
2365 if (r < 0)
2366 return r;
2367
2368 rc = sym_Esys_StartAuthSession(
2369 c->esys_context,
2370 primary->esys_handle,
2371 ESYS_TR_NONE,
2372 encryption_session->esys_handle,
2373 ESYS_TR_NONE,
2374 ESYS_TR_NONE,
2375 NULL,
2376 session_type,
a47060bb 2377 &SESSION_TEMPLATE_SYM_AES_128_CFB,
2cd9d575
DS
2378 TPM2_ALG_SHA256,
2379 &session->esys_handle);
2380 if (rc != TSS2_RC_SUCCESS)
2381 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2382 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2383
2384 *ret_session = TAKE_PTR(session);
2385
2386 return 0;
2387}
2388
95898241
DS
2389static int openssl_pubkey_to_tpm2_pubkey(
2390 const void *pubkey,
2391 size_t pubkey_size,
2392 TPM2B_PUBLIC *output,
2393 void **ret_fp,
2394 size_t *ret_fp_size) {
2395
395c1d9a 2396#if HAVE_OPENSSL
d9b5841d
LP
2397#if OPENSSL_VERSION_MAJOR >= 3
2398 _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL;
2399#else
2400 const BIGNUM *n = NULL, *e = NULL;
2401 const RSA *rsa = NULL;
2402#endif
95898241 2403 int r, n_bytes, e_bytes;
d9b5841d 2404
95898241
DS
2405 assert(pubkey);
2406 assert(pubkey_size > 0);
d9b5841d
LP
2407 assert(output);
2408
2409 /* Converts an OpenSSL public key to a structure that the TPM chip can process. */
2410
95898241
DS
2411 _cleanup_fclose_ FILE *f = NULL;
2412 f = fmemopen((void*) pubkey, pubkey_size, "r");
2413 if (!f)
2414 return log_oom();
2415
2416 _cleanup_(EVP_PKEY_freep) EVP_PKEY *input = NULL;
2417 input = PEM_read_PUBKEY(f, NULL, NULL, NULL);
2418 if (!input)
2419 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
2420
d9b5841d
LP
2421 if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA)
2422 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key.");
2423
2424#if OPENSSL_VERSION_MAJOR >= 3
2425 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_N, &n))
2426 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
2427#else
2428 rsa = EVP_PKEY_get0_RSA(input);
2429 if (!rsa)
2430 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to extract RSA key from public key.");
2431
2432 n = RSA_get0_n(rsa);
2433 if (!n)
2434 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
2435#endif
2436
2437 n_bytes = BN_num_bytes(n);
2438 assert_se(n_bytes > 0);
2439 if ((size_t) n_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.unique.rsa.buffer))
2440 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA modulus too large for TPM2 public key object.");
2441
2442#if OPENSSL_VERSION_MAJOR >= 3
2443 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_E, &e))
2444 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
2445#else
2446 e = RSA_get0_e(rsa);
2447 if (!e)
2448 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
2449#endif
2450
2451 e_bytes = BN_num_bytes(e);
2452 assert_se(e_bytes > 0);
2453 if ((size_t) e_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.parameters.rsaDetail.exponent))
2454 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA exponent too large for TPM2 public key object.");
2455
2456 *output = (TPM2B_PUBLIC) {
2457 .size = sizeof(TPMT_PUBLIC),
2458 .publicArea = {
2459 .type = TPM2_ALG_RSA,
2460 .nameAlg = TPM2_ALG_SHA256,
2461 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
2462 .parameters.rsaDetail = {
2463 .scheme = {
2464 .scheme = TPM2_ALG_NULL,
2465 .details.anySig.hashAlg = TPM2_ALG_NULL,
2466 },
2467 .symmetric = {
2468 .algorithm = TPM2_ALG_NULL,
2469 .mode.sym = TPM2_ALG_NULL,
2470 },
2471 .keyBits = n_bytes * 8,
2472 /* .exponent will be filled in below. */
2473 },
2474 .unique = {
2475 .rsa.size = n_bytes,
2476 /* .rsa.buffer will be filled in below. */
2477 },
2478 },
2479 };
2480
2481 if (BN_bn2bin(n, output->publicArea.unique.rsa.buffer) <= 0)
2482 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA modulus.");
2483
2484 if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0)
2485 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent.");
2486
95898241
DS
2487 if (ret_fp) {
2488 _cleanup_free_ void *fp = NULL;
2489 size_t fp_size;
2490
2491 assert(ret_fp_size);
2492
2493 r = pubkey_fingerprint(input, EVP_sha256(), &fp, &fp_size);
2494 if (r < 0)
2495 return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
2496
2497 *ret_fp = TAKE_PTR(fp);
2498 *ret_fp_size = fp_size;
2499 }
2500
d9b5841d 2501 return 0;
95898241
DS
2502#else /* HAVE_OPENSSL */
2503 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2504#endif
d9b5841d
LP
2505}
2506
2507static int find_signature(
2508 JsonVariant *v,
95898241
DS
2509 const TPML_PCR_SELECTION *pcr_selection,
2510 const void *fp,
2511 size_t fp_size,
d9b5841d
LP
2512 const void *policy,
2513 size_t policy_size,
2514 void *ret_signature,
2515 size_t *ret_signature_size) {
2516
95898241 2517#if HAVE_OPENSSL
d9b5841d 2518 JsonVariant *b, *i;
d9b5841d
LP
2519 const char *k;
2520 int r;
2521
2522 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
2523 * public key, and policy digest. */
2524
2525 if (!json_variant_is_object(v))
2526 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
2527
95898241
DS
2528 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
2529 uint32_t pcr_mask;
2530 r = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank, &pcr_mask);
2531 if (r < 0)
2532 return r;
2533
7bfe0a48 2534 k = tpm2_hash_alg_to_string(pcr_bank);
d9b5841d
LP
2535 if (!k)
2536 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
2537
2538 /* First, find field by bank */
2539 b = json_variant_by_key(v, k);
2540 if (!b)
2541 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
2542
2543 if (!json_variant_is_array(b))
2544 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
2545
2546 /* Now iterate through all signatures known for this bank */
2547 JSON_VARIANT_ARRAY_FOREACH(i, b) {
2548 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
2549 JsonVariant *maskj, *fpj, *sigj, *polj;
2550 size_t fpj_size, polj_size;
2551 uint32_t parsed_mask;
2552
2553 if (!json_variant_is_object(i))
2554 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
2555
2556 /* Check if the PCR mask matches our expectations */
2557 maskj = json_variant_by_key(i, "pcrs");
2558 if (!maskj)
2559 continue;
2560
2561 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
2562 if (r < 0)
2563 return log_error_errno(r, "Failed to parse JSON PCR mask");
2564
2565 if (parsed_mask != pcr_mask)
2566 continue; /* Not for this PCR mask */
2567
2568 /* Then check if this is for the public key we operate with */
2569 fpj = json_variant_by_key(i, "pkfp");
2570 if (!fpj)
2571 continue;
2572
2573 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
2574 if (r < 0)
2575 return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
2576
d9b5841d
LP
2577 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
2578 continue; /* Not for this public key */
2579
2580 /* Finally, check if this is for the PCR policy we expect this to be */
2581 polj = json_variant_by_key(i, "pol");
2582 if (!polj)
2583 continue;
2584
2585 r = json_variant_unhex(polj, &polj_data, &polj_size);
2586 if (r < 0)
2587 return log_error_errno(r, "Failed to decode policy hash JSON data: %m");
2588
2589 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
2590 continue;
2591
2592 /* This entry matches all our expectations, now return the signature included in it */
2593 sigj = json_variant_by_key(i, "sig");
2594 if (!sigj)
2595 continue;
2596
2597 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
2598 }
2599
2600 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
95898241
DS
2601#else /* HAVE_OPENSSL */
2602 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
395c1d9a 2603#endif
95898241 2604}
d9b5841d 2605
dbae4b95
DS
2606/* Calculates the "name" of a public key.
2607 *
2608 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
2609 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
2610 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
2611 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
2612 * that would also change the key name.
2613 *
2614 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
2615 * nameAlg is not TPM2_ALG_SHA256. */
2616int tpm2_calculate_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
2617 TSS2_RC rc;
2618 int r;
2619
2620 assert(public);
2621 assert(ret_name);
2622
2623 r = dlopen_tpm2();
2624 if (r < 0)
2625 return log_error_errno(r, "TPM2 support not installed: %m");
2626
2627 if (public->nameAlg != TPM2_ALG_SHA256)
2628 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2629 "Unsupported nameAlg: 0x%x",
2630 public->nameAlg);
2631
2632 _cleanup_free_ uint8_t *buf = NULL;
2633 size_t size = 0;
2634
2635 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
2636 if (!buf)
2637 return log_oom();
2638
2639 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
2640 if (rc != TSS2_RC_SUCCESS)
2641 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2642 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
2643
2644 TPM2B_DIGEST digest = {};
2645 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
2646 if (r < 0)
2647 return r;
2648
2649 TPMT_HA ha = {
2650 .hashAlg = TPM2_ALG_SHA256,
2651 };
2652 assert(digest.size <= sizeof(ha.digest.sha256));
2653 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
2654
2655 TPM2B_NAME name;
2656 size = 0;
2657 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
2658 if (rc != TSS2_RC_SUCCESS)
2659 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2660 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
2661 name.size = size;
2662
2663 tpm2_log_debug_name(&name, "Calculated name");
2664
2665 *ret_name = name;
2666
2667 return 0;
2668}
2669
2670/* Get the "name" of a key from the TPM.
2671 *
2672 * The "name" of a key is explained above in tpm2_calculate_name().
2673 *
2674 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
2675 * public/private keypair. */
2676static int tpm2_get_name(
2677 Tpm2Context *c,
2678 const Tpm2Handle *handle,
2679 TPM2B_NAME **ret_name) {
2680
2681 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
2682 TSS2_RC rc;
2683
2684 assert(c);
2685 assert(handle);
2686 assert(ret_name);
2687
2688 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
2689 if (rc != TSS2_RC_SUCCESS)
2690 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2691 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
2692
2693 tpm2_log_debug_name(name, "Object name");
2694
2695 *ret_name = TAKE_PTR(name);
2696
2697 return 0;
2698}
2699
8a716354
DS
2700/* Extend 'digest' with the PolicyAuthValue calculated hash. */
2701int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
2702 TPM2_CC command = TPM2_CC_PolicyAuthValue;
2703 TSS2_RC rc;
2704 int r;
2705
2706 assert(digest);
2707 assert(digest->size == SHA256_DIGEST_SIZE);
2708
2709 r = dlopen_tpm2();
2710 if (r < 0)
2711 return log_error_errno(r, "TPM2 support not installed: %m");
2712
2713 uint8_t buf[sizeof(command)];
2714 size_t offset = 0;
2715
2716 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
2717 if (rc != TSS2_RC_SUCCESS)
2718 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2719 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
2720
2721 if (offset != sizeof(command))
2722 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2723 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
2724
2725 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
2726 if (r < 0)
2727 return r;
2728
2729 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
2730
2731 return 0;
2732}
2733
2734static int tpm2_policy_auth_value(
2735 Tpm2Context *c,
2736 const Tpm2Handle *session,
2737 TPM2B_DIGEST **ret_policy_digest) {
2738
2739 TSS2_RC rc;
2740
2741 assert(c);
2742 assert(session);
2743
2744 log_debug("Adding authValue policy.");
2745
2746 rc = sym_Esys_PolicyAuthValue(
2747 c->esys_context,
2748 session->esys_handle,
2749 ESYS_TR_NONE,
2750 ESYS_TR_NONE,
2751 ESYS_TR_NONE);
2752 if (rc != TSS2_RC_SUCCESS)
2753 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2754 "Failed to add authValue policy to TPM: %s",
2755 sym_Tss2_RC_Decode(rc));
2756
2757 return tpm2_get_policy_digest(c, session, ret_policy_digest);
2758}
2759
dcbc4674
DS
2760/* Extend 'digest' with the PolicyPCR calculated hash. */
2761int tpm2_calculate_policy_pcr(
2762 const TPML_PCR_SELECTION *pcr_selection,
2763 const TPM2B_DIGEST pcr_values[],
2764 size_t n_pcr_values,
2765 TPM2B_DIGEST *digest) {
2766
2767 TPM2_CC command = TPM2_CC_PolicyPCR;
2768 TSS2_RC rc;
2769 int r;
2770
2771 assert(pcr_selection);
2772 assert(pcr_values || n_pcr_values == 0);
2773 assert(digest);
2774 assert(digest->size == SHA256_DIGEST_SIZE);
2775
2776 r = dlopen_tpm2();
2777 if (r < 0)
2778 return log_error_errno(r, "TPM2 support not installed: %m");
2779
2780 TPM2B_DIGEST hash = {};
2781 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, pcr_values, n_pcr_values, /* extend= */ false);
2782 if (r < 0)
2783 return r;
2784
2785 _cleanup_free_ uint8_t *buf = NULL;
2786 size_t size = 0, maxsize = sizeof(command) + sizeof(*pcr_selection);
2787
2788 buf = malloc(maxsize);
2789 if (!buf)
2790 return log_oom();
2791
2792 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
2793 if (rc != TSS2_RC_SUCCESS)
2794 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2795 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
2796
2797 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(pcr_selection, buf, maxsize, &size);
2798 if (rc != TSS2_RC_SUCCESS)
2799 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2800 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
2801
2802 struct iovec data[] = {
2803 IOVEC_MAKE(buf, size),
2804 IOVEC_MAKE(hash.buffer, hash.size),
2805 };
2806 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
2807 if (r < 0)
2808 return r;
2809
2810 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
2811
2812 return 0;
2813}
2814
2815static int tpm2_policy_pcr(
2816 Tpm2Context *c,
2817 const Tpm2Handle *session,
2818 const TPML_PCR_SELECTION *pcr_selection,
2819 TPM2B_DIGEST **ret_policy_digest) {
2820
2821 TSS2_RC rc;
2822
2823 assert(c);
2824 assert(session);
2825 assert(pcr_selection);
2826
2827 log_debug("Adding PCR hash policy.");
2828
2829 rc = sym_Esys_PolicyPCR(
2830 c->esys_context,
2831 session->esys_handle,
2832 ESYS_TR_NONE,
2833 ESYS_TR_NONE,
2834 ESYS_TR_NONE,
2835 NULL,
2836 pcr_selection);
2837 if (rc != TSS2_RC_SUCCESS)
2838 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2839 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
2840
2841 return tpm2_get_policy_digest(c, session, ret_policy_digest);
2842}
2843
5c7852f7
DS
2844/* Extend 'digest' with the PolicyAuthorize calculated hash. */
2845int tpm2_calculate_policy_authorize(
2846 const TPM2B_PUBLIC *public,
2847 const TPM2B_DIGEST *policy_ref,
2848 TPM2B_DIGEST *digest) {
2849
2850 TPM2_CC command = TPM2_CC_PolicyAuthorize;
2851 TSS2_RC rc;
2852 int r;
2853
2854 assert(public);
2855 assert(digest);
2856 assert(digest->size == SHA256_DIGEST_SIZE);
2857
2858 r = dlopen_tpm2();
2859 if (r < 0)
2860 return log_error_errno(r, "TPM2 support not installed: %m");
2861
2862 uint8_t buf[sizeof(command)];
2863 size_t offset = 0;
2864
2865 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
2866 if (rc != TSS2_RC_SUCCESS)
2867 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2868 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
2869
2870 if (offset != sizeof(command))
2871 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2872 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
2873
2874 TPM2B_NAME name = {};
2875 r = tpm2_calculate_name(&public->publicArea, &name);
2876 if (r < 0)
2877 return r;
2878
2879 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
2880 zero(digest->buffer);
2881
2882 struct iovec data[] = {
2883 IOVEC_MAKE(buf, offset),
2884 IOVEC_MAKE(name.name, name.size),
2885 };
2886 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
2887 if (r < 0)
2888 return r;
2889
2890 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
2891 if (policy_ref)
2892 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
2893 else
2894 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
2895 if (r < 0)
2896 return r;
2897
2898 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
2899
2900 return 0;
2901}
2902
2903static int tpm2_policy_authorize(
2904 Tpm2Context *c,
2905 const Tpm2Handle *session,
2906 TPML_PCR_SELECTION *pcr_selection,
2907 const TPM2B_PUBLIC *public,
2908 const void *fp,
2909 size_t fp_size,
2910 JsonVariant *signature_json,
2911 TPM2B_DIGEST **ret_policy_digest) {
2912
2913 TSS2_RC rc;
2914 int r;
2915
2916 assert(c);
2917 assert(session);
2918 assert(pcr_selection);
2919 assert(public);
2920 assert(fp && fp_size > 0);
2921
2922 log_debug("Adding PCR signature policy.");
2923
1dc8f518 2924 _cleanup_(tpm2_handle_freep) Tpm2Handle *pubkey_handle = NULL;
efe153bd 2925 r = tpm2_load_external(c, NULL, public, NULL, &pubkey_handle);
5c7852f7
DS
2926 if (r < 0)
2927 return r;
2928
5c7852f7
DS
2929 /* Acquire the "name" of what we just loaded */
2930 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
2931 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
2932 if (r < 0)
2933 return r;
2934
2935 /* If we have a signature, proceed with verifying the PCR digest */
2936 const TPMT_TK_VERIFIED *check_ticket;
2937 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
2938 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
2939 if (signature_json) {
2940 r = tpm2_policy_pcr(
2941 c,
2942 session,
2943 pcr_selection,
2944 &approved_policy);
2945 if (r < 0)
2946 return r;
2947
2948 _cleanup_free_ void *signature_raw = NULL;
2949 size_t signature_size;
2950
2951 r = find_signature(
2952 signature_json,
2953 pcr_selection,
2954 fp, fp_size,
2955 approved_policy->buffer,
2956 approved_policy->size,
2957 &signature_raw,
2958 &signature_size);
2959 if (r < 0)
2960 return r;
2961
2962 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
2963 * hence we need to do the SHA256 part ourselves, first */
2964 TPM2B_DIGEST signature_hash = *approved_policy;
2965 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
2966 if (r < 0)
2967 return r;
2968
2969 TPMT_SIGNATURE policy_signature = {
2970 .sigAlg = TPM2_ALG_RSASSA,
2971 .signature.rsassa = {
2972 .hash = TPM2_ALG_SHA256,
2973 .sig.size = signature_size,
2974 },
2975 };
2976 if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer))
2977 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
2978 memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
2979
2980 rc = sym_Esys_VerifySignature(
2981 c->esys_context,
2982 pubkey_handle->esys_handle,
2983 ESYS_TR_NONE,
2984 ESYS_TR_NONE,
2985 ESYS_TR_NONE,
2986 &signature_hash,
2987 &policy_signature,
2988 &check_ticket_buffer);
2989 if (rc != TSS2_RC_SUCCESS)
2990 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2991 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
2992
2993 check_ticket = check_ticket_buffer;
2994 } else {
2995 /* When enrolling, we pass a NULL ticket */
2996 static const TPMT_TK_VERIFIED check_ticket_null = {
2997 .tag = TPM2_ST_VERIFIED,
2998 .hierarchy = TPM2_RH_OWNER,
2999 };
3000
3001 check_ticket = &check_ticket_null;
3002 }
3003
3004 rc = sym_Esys_PolicyAuthorize(
3005 c->esys_context,
3006 session->esys_handle,
3007 ESYS_TR_NONE,
3008 ESYS_TR_NONE,
3009 ESYS_TR_NONE,
3010 approved_policy,
3011 /* policyRef= */ &(const TPM2B_NONCE) {},
3012 pubkey_name,
3013 check_ticket);
3014 if (rc != TSS2_RC_SUCCESS)
3015 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3016 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
3017
3018 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3019}
3020
d9a1f1a7
DS
3021/* Extend 'digest' with the calculated policy hash. */
3022static int tpm2_calculate_sealing_policy(
3023 const TPML_PCR_SELECTION *hash_pcr_selection,
3024 const TPM2B_DIGEST *hash_pcr_values,
3025 size_t n_hash_pcr_values,
3026 const TPM2B_PUBLIC *public,
3027 const char *pin,
3028 TPM2B_DIGEST *digest) {
3029
3030 int r;
3031
3032 assert(digest);
3033
3034 if (public) {
3035 r = tpm2_calculate_policy_authorize(public, NULL, digest);
3036 if (r < 0)
3037 return r;
3038 }
3039
3040 if (hash_pcr_selection && !tpm2_tpml_pcr_selection_is_empty(hash_pcr_selection)) {
3041 r = tpm2_calculate_policy_pcr(hash_pcr_selection, hash_pcr_values, n_hash_pcr_values, digest);
3042 if (r < 0)
3043 return r;
3044 }
3045
3046 if (pin) {
3047 r = tpm2_calculate_policy_auth_value(digest);
3048 if (r < 0)
3049 return r;
3050 }
3051
3052 return 0;
3053}
3054
2cd9d575 3055static int tpm2_build_sealing_policy(
23e9ccc2 3056 Tpm2Context *c,
2cd9d575 3057 const Tpm2Handle *session,
d9b5841d 3058 uint32_t hash_pcr_mask,
2cd9d575 3059 uint16_t pcr_bank,
524cef3f
DS
3060 const TPM2B_PUBLIC *public,
3061 const void *fp,
3062 size_t fp_size,
d9b5841d
LP
3063 uint32_t pubkey_pcr_mask,
3064 JsonVariant *signature_json,
2f5a892a 3065 bool use_pin,
2cd9d575 3066 TPM2B_DIGEST **ret_policy_digest) {
5e521624 3067
5e521624
LP
3068 int r;
3069
3070 assert(c);
2cd9d575 3071 assert(session);
524cef3f 3072 assert(pubkey_pcr_mask == 0 || public);
5e521624 3073
2cd9d575 3074 log_debug("Building sealing policy.");
251d2ea2 3075
d9b5841d 3076 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
2cd9d575
DS
3077 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
3078 if (r < 0)
3079 return r;
3080 if (r == 0)
3081 log_warning("Selected TPM2 PCRs are not initialized on this system.");
d9b5841d 3082 }
321a9d9e 3083
d9b5841d 3084 if (pubkey_pcr_mask != 0) {
d9b5841d 3085 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 3086 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
524cef3f 3087 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
23b972d5
DS
3088 if (r < 0)
3089 return r;
d9b5841d
LP
3090 }
3091
3092 if (hash_pcr_mask != 0) {
d9b5841d 3093 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 3094 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
dcbc4674
DS
3095 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
3096 if (r < 0)
3097 return r;
5e521624
LP
3098 }
3099
2f5a892a 3100 if (use_pin) {
8a716354
DS
3101 r = tpm2_policy_auth_value(c, session, NULL);
3102 if (r < 0)
3103 return r;
2f5a892a
GG
3104 }
3105
23b972d5
DS
3106 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
3107 if (r < 0)
3108 return r;
5e521624 3109
16e16b8c 3110 return 0;
5e521624
LP
3111}
3112
d9b5841d
LP
3113int tpm2_seal(const char *device,
3114 uint32_t hash_pcr_mask,
3115 const void *pubkey,
3116 const size_t pubkey_size,
3117 uint32_t pubkey_pcr_mask,
3118 const char *pin,
3119 void **ret_secret,
3120 size_t *ret_secret_size,
3121 void **ret_blob,
3122 size_t *ret_blob_size,
3123 void **ret_pcr_hash,
3124 size_t *ret_pcr_hash_size,
3125 uint16_t *ret_pcr_bank,
acbb504e
WR
3126 uint16_t *ret_primary_alg,
3127 void **ret_srk_buf,
3128 size_t *ret_srk_buf_size) {
5e521624 3129
5e521624
LP
3130 TSS2_RC rc;
3131 int r;
3132
d9b5841d
LP
3133 assert(pubkey || pubkey_size == 0);
3134
5e521624
LP
3135 assert(ret_secret);
3136 assert(ret_secret_size);
3137 assert(ret_blob);
3138 assert(ret_blob_size);
3139 assert(ret_pcr_hash);
3140 assert(ret_pcr_hash_size);
07697bfe 3141 assert(ret_pcr_bank);
5e521624 3142
d9b5841d
LP
3143 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
3144 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624
LP
3145
3146 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3147 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
2b92a672
LP
3148 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3149 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3150 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3151 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3152 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3153 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3154 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3155 * LUKS2 JSON header.
5e521624
LP
3156 *
3157 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3158 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3159 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3160 * binding the unlocking to the TPM2 chip. */
3161
ee6a8713 3162 usec_t start = now(CLOCK_MONOTONIC);
692597c8 3163
1dc8f518 3164 _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
68d084ce 3165 r = tpm2_context_new(device, &c);
5e521624
LP
3166 if (r < 0)
3167 return r;
3168
2cd9d575
DS
3169 TPMI_ALG_HASH pcr_bank = 0;
3170 if (hash_pcr_mask | pubkey_pcr_mask) {
3171 /* Some TPM2 devices only can do SHA1. Prefer SHA256 but allow SHA1. */
3172 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
3173 if (r < 0)
3174 return r;
3175 }
3176
d9a1f1a7
DS
3177 TPML_PCR_SELECTION hash_pcr_selection = {};
3178 _cleanup_free_ TPM2B_DIGEST *hash_pcr_values = NULL;
3179 size_t n_hash_pcr_values = 0;
3180 if (hash_pcr_mask) {
3181 /* For now, we just read the current values from the system; we need to be able to specify
3182 * expected values, eventually. */
3183 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, pcr_bank, &hash_pcr_selection);
3184 r = tpm2_pcr_read(c, &hash_pcr_selection, &hash_pcr_selection, &hash_pcr_values, &n_hash_pcr_values);
3185 if (r < 0)
3186 return r;
3187 }
3188
524cef3f 3189 TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
524cef3f 3190 if (pubkey) {
d9a1f1a7 3191 r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, NULL, NULL);
524cef3f
DS
3192 if (r < 0)
3193 return r;
3194 authorize_key = &pubkey_tpm2;
3195 }
3196
d9a1f1a7
DS
3197 TPM2B_DIGEST policy_digest;
3198 r = tpm2_digest_init(TPM2_ALG_SHA256, &policy_digest);
2cd9d575
DS
3199 if (r < 0)
3200 return r;
3201
d9a1f1a7
DS
3202 r = tpm2_calculate_sealing_policy(
3203 &hash_pcr_selection,
3204 hash_pcr_values,
3205 n_hash_pcr_values,
524cef3f 3206 authorize_key,
d9a1f1a7 3207 pin,
2cd9d575 3208 &policy_digest);
5e521624 3209 if (r < 0)
16e16b8c 3210 return r;
5e521624
LP
3211
3212 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3213 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3214 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
e3f1f210
DS
3215 TPMT_PUBLIC hmac_template = {
3216 .type = TPM2_ALG_KEYEDHASH,
3217 .nameAlg = TPM2_ALG_SHA256,
3218 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
3219 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
3220 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
3221 .authPolicy = policy_digest,
5e521624
LP
3222 };
3223
e3f1f210
DS
3224 TPMS_SENSITIVE_CREATE hmac_sensitive = {
3225 .data.size = hmac_template.unique.keyedHash.size,
5e521624 3226 };
ee6a8713
DS
3227
3228 CLEANUP_ERASE(hmac_sensitive);
3229
94a4ff2d 3230 if (pin) {
e3f1f210 3231 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &hmac_sensitive.userAuth, pin, strlen(pin), /* extend= */ false);
94a4ff2d
DS
3232 if (r < 0)
3233 return r;
3234 }
0e15c14f 3235
e3f1f210 3236 assert(sizeof(hmac_sensitive.data.buffer) >= hmac_sensitive.data.size);
5e521624 3237
23e9ccc2 3238 (void) tpm2_credit_random(c);
5e521624
LP
3239
3240 log_debug("Generating secret key data.");
3241
e3f1f210 3242 r = crypto_random_bytes(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
16e16b8c
DS
3243 if (r < 0)
3244 return log_error_errno(r, "Failed to generate secret key: %m");
5e521624 3245
cea525a9 3246 _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
1dc8f518 3247 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
cea525a9
DS
3248 if (ret_srk_buf) {
3249 r = tpm2_get_or_create_srk(c, NULL, &primary_public, NULL, NULL, &primary_handle);
3250 if (r < 0)
3251 return r;
3252 } else {
3253 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
3254 TPMT_PUBLIC template;
3255 r = tpm2_get_legacy_template(TPM2_ALG_ECC, &template);
3256 if (r < 0)
3257 return log_error_errno(r, "Could not get legacy ECC template: %m");
3258
3259 if (!tpm2_supports_tpmt_public(c, &template)) {
3260 r = tpm2_get_legacy_template(TPM2_ALG_RSA, &template);
3261 if (r < 0)
3262 return log_error_errno(r, "Could not get legacy RSA template: %m");
3263
3264 if (!tpm2_supports_tpmt_public(c, &template))
3265 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3266 "TPM does not support either ECC or RSA legacy template.");
3267 }
3268
3269 r = tpm2_create_loaded(
3270 c,
3271 /* parent= */ NULL,
3272 /* session= */ NULL,
3273 &template,
3274 /* sensitive= */ NULL,
3275 &primary_public,
3276 /* ret_private= */ NULL,
3277 &primary_handle);
3278 if (r < 0)
3279 return r;
3280 }
d9a1f1a7 3281
1dc8f518 3282 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
d9a1f1a7
DS
3283 r = tpm2_make_encryption_session(c, primary_handle, &TPM2_HANDLE_NONE, &encryption_session);
3284 if (r < 0)
3285 return r;
3286
ee6a8713
DS
3287 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
3288 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
e3f1f210
DS
3289 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
3290 if (r < 0)
3291 return r;
5e521624 3292
ee6a8713 3293 _cleanup_(erase_and_freep) void *secret = NULL;
e3f1f210 3294 secret = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
16e16b8c
DS
3295 if (!secret)
3296 return log_oom();
5e521624
LP
3297
3298 log_debug("Marshalling private and public part of HMAC key.");
3299
e8858f11
DS
3300 _cleanup_free_ void *blob = NULL;
3301 size_t max_size = sizeof(*private) + sizeof(*public), blob_size = 0;
5e521624 3302
e8858f11
DS
3303 blob = malloc0(max_size);
3304 if (!blob)
3305 return log_oom();
5e521624 3306
e8858f11
DS
3307 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
3308 if (rc != TSS2_RC_SUCCESS)
3309 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3310 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
5e521624 3311
e8858f11
DS
3312 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
3313 if (rc != TSS2_RC_SUCCESS)
3314 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3315 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
5e521624 3316
ee6a8713 3317 _cleanup_free_ void *hash = NULL;
d9a1f1a7 3318 hash = memdup(policy_digest.buffer, policy_digest.size);
5e521624
LP
3319 if (!hash)
3320 return log_oom();
3321
acbb504e
WR
3322 /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
3323 * the raw TPM handle as well as the object name. The object name is used to verify that
3324 * the key we use later is the key we expect to establish the session with.
3325 */
ee6a8713
DS
3326 _cleanup_(Esys_Freep) uint8_t *srk_buf = NULL;
3327 size_t srk_buf_size = 0;
acbb504e
WR
3328 if (ret_srk_buf) {
3329 log_debug("Serializing SRK ESYS_TR reference");
d9a1f1a7 3330 rc = sym_Esys_TR_Serialize(c->esys_context, primary_handle->esys_handle, &srk_buf, &srk_buf_size);
acbb504e
WR
3331 if (rc != TSS2_RC_SUCCESS)
3332 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3333 "Failed to serialize primary key: %s", sym_Tss2_RC_Decode(rc));
3334 }
3335
5291f26d
ZJS
3336 if (DEBUG_LOGGING)
3337 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624 3338
acbb504e
WR
3339 if (ret_srk_buf) {
3340 /*
3341 * make a copy since we don't want the caller to understand that
3342 * ESYS allocated the pointer. It would make tracking what deallocator
3343 * to use for srk_buf in which context a PITA.
3344 */
3345 void *tmp = memdup(srk_buf, srk_buf_size);
3346 if (!tmp)
3347 return log_oom();
3348
3349 *ret_srk_buf = TAKE_PTR(tmp);
3350 *ret_srk_buf_size = srk_buf_size;
3351 }
3352
5e521624 3353 *ret_secret = TAKE_PTR(secret);
e3f1f210 3354 *ret_secret_size = hmac_sensitive.data.size;
5e521624
LP
3355 *ret_blob = TAKE_PTR(blob);
3356 *ret_blob_size = blob_size;
3357 *ret_pcr_hash = TAKE_PTR(hash);
d9a1f1a7 3358 *ret_pcr_hash_size = policy_digest.size;
07697bfe 3359 *ret_pcr_bank = pcr_bank;
cea525a9 3360 *ret_primary_alg = primary_public->publicArea.type;
5e521624 3361
16e16b8c 3362 return 0;
5e521624
LP
3363}
3364
0254e4d6
AAF
3365#define RETRY_UNSEAL_MAX 30u
3366
d9b5841d
LP
3367int tpm2_unseal(const char *device,
3368 uint32_t hash_pcr_mask,
07697bfe 3369 uint16_t pcr_bank,
d9b5841d
LP
3370 const void *pubkey,
3371 size_t pubkey_size,
3372 uint32_t pubkey_pcr_mask,
3373 JsonVariant *signature,
3374 const char *pin,
2b92a672 3375 uint16_t primary_alg,
5e521624
LP
3376 const void *blob,
3377 size_t blob_size,
3378 const void *known_policy_hash,
3379 size_t known_policy_hash_size,
acbb504e
WR
3380 const void *srk_buf,
3381 size_t srk_buf_size,
5e521624
LP
3382 void **ret_secret,
3383 size_t *ret_secret_size) {
3384
5e521624 3385 TSS2_RC rc;
5e521624
LP
3386 int r;
3387
3388 assert(blob);
3389 assert(blob_size > 0);
3390 assert(known_policy_hash_size == 0 || known_policy_hash);
d9b5841d 3391 assert(pubkey_size == 0 || pubkey);
5e521624
LP
3392 assert(ret_secret);
3393 assert(ret_secret_size);
3394
d9b5841d
LP
3395 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
3396 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624 3397
1b30720c
LP
3398 r = dlopen_tpm2();
3399 if (r < 0)
3400 return log_error_errno(r, "TPM2 support is not installed.");
3401
5e521624 3402 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
dc176813
ZJS
3403 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
3404 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
3405 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
3406 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
3407 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5e521624
LP
3408 * and use it to unlock the LUKS2 volume. */
3409
98497426 3410 usec_t start = now(CLOCK_MONOTONIC);
5e521624
LP
3411
3412 log_debug("Unmarshalling private part of HMAC key.");
3413
98497426
DS
3414 TPM2B_PRIVATE private = {};
3415 size_t offset = 0;
5e521624
LP
3416 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
3417 if (rc != TSS2_RC_SUCCESS)
3418 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3419 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
3420
3421 log_debug("Unmarshalling public part of HMAC key.");
3422
98497426 3423 TPM2B_PUBLIC public = {};
5e521624
LP
3424 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
3425 if (rc != TSS2_RC_SUCCESS)
3426 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3427 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
3428
1dc8f518 3429 _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
68d084ce 3430 r = tpm2_context_new(device, &c);
5e521624
LP
3431 if (r < 0)
3432 return r;
3433
20988602 3434 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
acbb504e 3435 if (srk_buf) {
20988602 3436 r = tpm2_handle_new(c, &primary_handle);
acbb504e
WR
3437 if (r < 0)
3438 return r;
3439
20988602 3440 primary_handle->flush = false;
acbb504e
WR
3441
3442 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
3443 rc = sym_Esys_TR_Deserialize(
3444 c->esys_context,
3445 srk_buf,
3446 srk_buf_size,
20988602 3447 &primary_handle->esys_handle);
acbb504e
WR
3448 if (rc != TSS2_RC_SUCCESS)
3449 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3450 "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc));
20988602
DS
3451 } else if (primary_alg != 0) {
3452 TPMT_PUBLIC template;
3453 r = tpm2_get_legacy_template(primary_alg, &template);
3454 if (r < 0)
3455 return log_error_errno(r, "Could not get legacy template: %m");
3456
3457 r = tpm2_create_loaded(
3458 c,
3459 /* parent= */ NULL,
3460 /* session= */ NULL,
3461 &template,
3462 /* sensitive= */ NULL,
3463 /* ret_public= */ NULL,
3464 /* ret_private= */ NULL,
3465 &primary_handle);
acbb504e
WR
3466 if (r < 0)
3467 return r;
20988602
DS
3468 } else
3469 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3470 "No SRK or primary alg provided.");
da29de23 3471
5e521624
LP
3472 log_debug("Loading HMAC key into TPM.");
3473
0e15c14f
WR
3474 /*
3475 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
acbb504e
WR
3476 * gives you back a different key, the session initiation will fail. In the
3477 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
3478 * provides protections.
0e15c14f 3479 */
1dc8f518 3480 _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
20988602 3481 r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
16e16b8c
DS
3482 if (r < 0)
3483 return r;
3484
524cef3f
DS
3485 TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
3486 _cleanup_free_ void *fp = NULL;
3487 size_t fp_size = 0;
3488 if (pubkey) {
3489 r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
3490 if (r < 0)
3491 return r;
3492 authorize_key = &pubkey_tpm2;
3493 }
3494
409a65f8
DS
3495 /*
3496 * if a pin is set for the seal object, use it to bind the session
3497 * key to that object. This prevents active bus interposers from
3498 * faking a TPM and seeing the unsealed value. An active interposer
3499 * could fake a TPM, satisfying the encrypted session, and just
3500 * forward everything to the *real* TPM.
3501 */
3502 r = tpm2_set_auth(c, hmac_key, pin);
3503 if (r < 0)
3504 return r;
3505
1dc8f518 3506 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
20988602 3507 r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
0e15c14f 3508 if (r < 0)
16e16b8c 3509 return r;
2f5a892a 3510
98497426 3511 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
0254e4d6 3512 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
1dc8f518 3513 _cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
23b972d5 3514 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
0254e4d6 3515 r = tpm2_make_policy_session(
23e9ccc2 3516 c,
20988602 3517 primary_handle,
2cd9d575
DS
3518 encryption_session,
3519 /* trial= */ false,
3520 &policy_session);
3521 if (r < 0)
3522 return r;
3523
3524 r = tpm2_build_sealing_policy(
3525 c,
3526 policy_session,
0254e4d6
AAF
3527 hash_pcr_mask,
3528 pcr_bank,
524cef3f
DS
3529 authorize_key,
3530 fp, fp_size,
0254e4d6
AAF
3531 pubkey_pcr_mask,
3532 signature,
3533 !!pin,
2cd9d575 3534 &policy_digest);
0254e4d6 3535 if (r < 0)
16e16b8c 3536 return r;
2f5a892a 3537
0254e4d6
AAF
3538 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
3539 * wait until the TPM2 tells us to go away. */
3540 if (known_policy_hash_size > 0 &&
3541 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
3542 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
3543 "Current policy digest does not match stored policy digest, cancelling "
3544 "TPM2 authentication attempt.");
2f5a892a 3545
0254e4d6 3546 log_debug("Unsealing HMAC key.");
5e521624 3547
0254e4d6 3548 rc = sym_Esys_Unseal(
68d084ce 3549 c->esys_context,
16e16b8c
DS
3550 hmac_key->esys_handle,
3551 policy_session->esys_handle,
2cd9d575 3552 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
0254e4d6
AAF
3553 ESYS_TR_NONE,
3554 &unsealed);
16e16b8c
DS
3555 if (rc == TSS2_RC_SUCCESS)
3556 break;
3557 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
3558 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3559 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
3560 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5e521624
LP
3561 }
3562
98497426 3563 _cleanup_(erase_and_freep) char *secret = NULL;
5e521624
LP
3564 secret = memdup(unsealed->buffer, unsealed->size);
3565 explicit_bzero_safe(unsealed->buffer, unsealed->size);
16e16b8c
DS
3566 if (!secret)
3567 return log_oom();
5e521624 3568
5291f26d
ZJS
3569 if (DEBUG_LOGGING)
3570 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624
LP
3571
3572 *ret_secret = TAKE_PTR(secret);
3573 *ret_secret_size = unsealed->size;
3574
16e16b8c 3575 return 0;
5e521624
LP
3576}
3577
3578#endif
3579
3580int tpm2_list_devices(void) {
3581#if HAVE_TPM2
3582 _cleanup_(table_unrefp) Table *t = NULL;
5d2a48da 3583 _cleanup_closedir_ DIR *d = NULL;
5e521624
LP
3584 int r;
3585
3586 r = dlopen_tpm2();
3587 if (r < 0)
3588 return log_error_errno(r, "TPM2 support is not installed.");
3589
3590 t = table_new("path", "device", "driver");
3591 if (!t)
3592 return log_oom();
3593
3594 d = opendir("/sys/class/tpmrm");
3595 if (!d) {
3596 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
3597 if (errno != ENOENT)
3598 return -errno;
3599 } else {
3600 for (;;) {
3601 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
3602 struct dirent *de;
3603
3604 de = readdir_no_dot(d);
3605 if (!de)
3606 break;
3607
3608 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
3609 if (!device_path)
3610 return log_oom();
3611
3612 r = readlink_malloc(device_path, &device);
3613 if (r < 0)
3614 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
3615 else {
3616 driver_path = path_join(device_path, "driver");
3617 if (!driver_path)
3618 return log_oom();
3619
3620 r = readlink_malloc(driver_path, &driver);
3621 if (r < 0)
3622 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
3623 }
3624
3625 node = path_join("/dev", de->d_name);
3626 if (!node)
3627 return log_oom();
3628
3629 r = table_add_many(
3630 t,
3631 TABLE_PATH, node,
3632 TABLE_STRING, device ? last_path_component(device) : NULL,
3633 TABLE_STRING, driver ? last_path_component(driver) : NULL);
3634 if (r < 0)
3635 return table_log_add_error(r);
3636 }
3637 }
3638
3639 if (table_get_rows(t) <= 1) {
3640 log_info("No suitable TPM2 devices found.");
3641 return 0;
3642 }
3643
3644 r = table_print(t, stdout);
3645 if (r < 0)
3646 return log_error_errno(r, "Failed to show device table: %m");
3647
3648 return 0;
3649#else
3650 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3651 "TPM2 not supported on this build.");
3652#endif
3653}
3654
3655int tpm2_find_device_auto(
3656 int log_level, /* log level when no device is found */
3657 char **ret) {
3658#if HAVE_TPM2
5d2a48da 3659 _cleanup_closedir_ DIR *d = NULL;
5e521624
LP
3660 int r;
3661
3662 r = dlopen_tpm2();
3663 if (r < 0)
3664 return log_error_errno(r, "TPM2 support is not installed.");
3665
3666 d = opendir("/sys/class/tpmrm");
3667 if (!d) {
3668 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
3669 "Failed to open /sys/class/tpmrm: %m");
3670 if (errno != ENOENT)
3671 return -errno;
3672 } else {
3673 _cleanup_free_ char *node = NULL;
3674
3675 for (;;) {
3676 struct dirent *de;
3677
3678 de = readdir_no_dot(d);
3679 if (!de)
3680 break;
3681
3682 if (node)
3683 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
3684 "More than one TPM2 (tpmrm) device found.");
3685
3686 node = path_join("/dev", de->d_name);
3687 if (!node)
3688 return log_oom();
3689 }
3690
3691 if (node) {
3692 *ret = TAKE_PTR(node);
3693 return 0;
3694 }
3695 }
3696
3697 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
3698#else
3699 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3700 "TPM2 not supported on this build.");
3701#endif
3702}
3703
15c591d1
LP
3704#if HAVE_TPM2
3705int tpm2_extend_bytes(
23e9ccc2 3706 Tpm2Context *c,
15c591d1
LP
3707 char **banks,
3708 unsigned pcr_index,
3709 const void *data,
9885c874
LP
3710 size_t data_size,
3711 const void *secret,
3712 size_t secret_size) {
15c591d1
LP
3713
3714#if HAVE_OPENSSL
3715 TPML_DIGEST_VALUES values = {};
3716 TSS2_RC rc;
3717
3718 assert(c);
9885c874
LP
3719 assert(data || data_size == 0);
3720 assert(secret || secret_size == 0);
3721
3722 if (data_size == SIZE_MAX)
3723 data_size = strlen(data);
3724 if (secret_size == SIZE_MAX)
3725 secret_size = strlen(secret);
15c591d1
LP
3726
3727 if (pcr_index >= TPM2_PCRS_MAX)
3728 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
3729
3730 if (strv_isempty(banks))
3731 return 0;
3732
3733 STRV_FOREACH(bank, banks) {
3734 const EVP_MD *implementation;
3735 int id;
3736
3737 assert_se(implementation = EVP_get_digestbyname(*bank));
3738
3739 if (values.count >= ELEMENTSOF(values.digests))
3740 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
3741
3742 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
3743 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
3744
7bfe0a48 3745 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
15c591d1
LP
3746 if (id < 0)
3747 return log_error_errno(id, "Can't map hash name to TPM2.");
3748
3749 values.digests[values.count].hashAlg = id;
3750
9885c874
LP
3751 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
3752 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
3753 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
3754 * secret for other purposes, maybe because it needs a shorter secret derived from it for
3755 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
3756 * private non-secret string instead. */
3757 if (secret_size > 0) {
3758 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
3759 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
3760 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
3761 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
15c591d1
LP
3762
3763 values.count++;
3764 }
3765
3766 rc = sym_Esys_PCR_Extend(
23e9ccc2 3767 c->esys_context,
15c591d1
LP
3768 ESYS_TR_PCR0 + pcr_index,
3769 ESYS_TR_PASSWORD,
3770 ESYS_TR_NONE,
3771 ESYS_TR_NONE,
3772 &values);
3773 if (rc != TSS2_RC_SUCCESS)
3774 return log_error_errno(
3775 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3776 "Failed to measure into PCR %u: %s",
3777 pcr_index,
3778 sym_Tss2_RC_Decode(rc));
3779
3780 return 0;
0d7009d3
DS
3781#else /* HAVE_OPENSSL */
3782 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
15c591d1
LP
3783#endif
3784}
3785#endif
3786
c69bd0ab
DS
3787char *tpm2_pcr_mask_to_string(uint32_t mask) {
3788 _cleanup_free_ char *s = NULL;
3789
3790 FOREACH_PCR_IN_MASK(n, mask)
3791 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
3792 return NULL;
3793
3794 if (!s)
3795 return strdup("");
3796
3797 return TAKE_PTR(s);
3798}
3799
3800int tpm2_pcr_mask_from_string(const char *arg, uint32_t *ret_mask) {
5e521624
LP
3801 uint32_t mask = 0;
3802 int r;
3803
c69bd0ab
DS
3804 assert(arg);
3805 assert(ret_mask);
3806
3807 if (isempty(arg)) {
3808 *ret_mask = 0;
d57f6340
LP
3809 return 0;
3810 }
3811
a1788a69
LP
3812 /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
3813 * and most other tools expect comma separated PCR specifications. We also support "+" since in
3814 * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
3815 * avoid escaping. */
5e521624 3816
c69bd0ab 3817 const char *p = arg;
5e521624
LP
3818 for (;;) {
3819 _cleanup_free_ char *pcr = NULL;
3820 unsigned n;
3821
a1788a69 3822 r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
5e521624
LP
3823 if (r == 0)
3824 break;
3825 if (r < 0)
c69bd0ab 3826 return log_error_errno(r, "Failed to parse PCR list: %s", arg);
5e521624 3827
96ead603 3828 r = pcr_index_from_string(pcr);
5e521624 3829 if (r < 0)
96ead603
OJ
3830 return log_error_errno(r, "Failed to parse specified PCR or specified PCR is out of range: %s", pcr);
3831 n = r;
0a3d108f 3832 SET_BIT(mask, n);
5e521624
LP
3833 }
3834
c69bd0ab 3835 *ret_mask = mask;
5e521624
LP
3836 return 0;
3837}
3838
4436081e
LP
3839int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
3840 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
3841 JsonVariant* pcr_array[TPM2_PCRS_MAX];
3842 unsigned n_pcrs = 0;
3843 int r;
3844
3845 for (size_t i = 0; i < ELEMENTSOF(pcr_array); i++) {
3846 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
3847 continue;
3848
3849 r = json_variant_new_integer(pcr_array + n_pcrs, i);
3850 if (r < 0)
3851 goto finish;
3852
3853 n_pcrs++;
3854 }
3855
3856 r = json_variant_new_array(&a, pcr_array, n_pcrs);
3857 if (r < 0)
3858 goto finish;
3859
3860 if (ret)
3861 *ret = TAKE_PTR(a);
3862 r = 0;
3863
3864finish:
ee9d31a6
DDM
3865 FOREACH_ARRAY(v, pcr_array, n_pcrs)
3866 json_variant_unref(*v);
3867
4436081e
LP
3868 return r;
3869}
8de8ec88
LP
3870
3871int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
3872 JsonVariant *e;
3873 uint32_t mask = 0;
3874
3875 if (!json_variant_is_array(v))
3876 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
3877
3878 JSON_VARIANT_ARRAY_FOREACH(e, v) {
3879 uint64_t u;
3880
3881 if (!json_variant_is_unsigned(e))
3882 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
3883
3884 u = json_variant_unsigned(e);
3885 if (u >= TPM2_PCRS_MAX)
3886 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
3887
3888 mask |= UINT32_C(1) << u;
3889 }
3890
3891 if (ret)
3892 *ret = mask;
3893
3894 return 0;
3895}
4436081e 3896
5e521624
LP
3897int tpm2_make_luks2_json(
3898 int keyslot,
f0f4fcae 3899 uint32_t hash_pcr_mask,
07697bfe 3900 uint16_t pcr_bank,
f0f4fcae
LP
3901 const void *pubkey,
3902 size_t pubkey_size,
3903 uint32_t pubkey_pcr_mask,
2b92a672 3904 uint16_t primary_alg,
5e521624
LP
3905 const void *blob,
3906 size_t blob_size,
3907 const void *policy_hash,
3908 size_t policy_hash_size,
aae6eb96
WR
3909 const void *salt,
3910 size_t salt_size,
acbb504e
WR
3911 const void *srk_buf,
3912 size_t srk_buf_size,
6c7a1681 3913 TPM2Flags flags,
5e521624
LP
3914 JsonVariant **ret) {
3915
f0f4fcae 3916 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
5e521624 3917 _cleanup_free_ char *keyslot_as_string = NULL;
5e521624
LP
3918 int r;
3919
3920 assert(blob || blob_size == 0);
3921 assert(policy_hash || policy_hash_size == 0);
f0f4fcae 3922 assert(pubkey || pubkey_size == 0);
5e521624
LP
3923
3924 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
3925 return -ENOMEM;
3926
f0f4fcae 3927 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
5e521624 3928 if (r < 0)
4436081e 3929 return r;
5e521624 3930
f0f4fcae
LP
3931 if (pubkey_pcr_mask != 0) {
3932 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
3933 if (r < 0)
3934 return r;
3935 }
3936
3937 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
3938 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
3939 * object should use "_" rather than "-" in field names. */
3940
5e521624
LP
3941 r = json_build(&v,
3942 JSON_BUILD_OBJECT(
0cdf6b14 3943 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
5e521624
LP
3944 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
3945 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
f0f4fcae 3946 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7bfe0a48
DS
3947 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
3948 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 3949 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
f0f4fcae
LP
3950 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
3951 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
aae6eb96 3952 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
acbb504e
WR
3953 JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size)),
3954 JSON_BUILD_PAIR_CONDITION(srk_buf, "tpm2_srk", JSON_BUILD_BASE64(srk_buf, srk_buf_size))));
5e521624
LP
3955 if (r < 0)
3956 return r;
3957
3958 if (ret)
3959 *ret = TAKE_PTR(v);
3960
3961 return keyslot;
3962}
07697bfe 3963
fdf6c27c
LP
3964int tpm2_parse_luks2_json(
3965 JsonVariant *v,
3966 int *ret_keyslot,
3967 uint32_t *ret_hash_pcr_mask,
3968 uint16_t *ret_pcr_bank,
3969 void **ret_pubkey,
3970 size_t *ret_pubkey_size,
3971 uint32_t *ret_pubkey_pcr_mask,
3972 uint16_t *ret_primary_alg,
3973 void **ret_blob,
3974 size_t *ret_blob_size,
3975 void **ret_policy_hash,
3976 size_t *ret_policy_hash_size,
aae6eb96
WR
3977 void **ret_salt,
3978 size_t *ret_salt_size,
acbb504e
WR
3979 void **ret_srk_buf,
3980 size_t *ret_srk_buf_size,
fdf6c27c
LP
3981 TPM2Flags *ret_flags) {
3982
acbb504e
WR
3983 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
3984 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
fdf6c27c
LP
3985 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
3986 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
3987 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
3988 int r, keyslot = -1;
3989 TPM2Flags flags = 0;
3990 JsonVariant *w;
3991
3992 assert(v);
3993
3994 if (ret_keyslot) {
3995 keyslot = cryptsetup_get_keyslot_from_token(v);
3996 if (keyslot < 0) {
3997 /* Return a recognizable error when parsing this field, so that callers can handle parsing
3998 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
3999 * spec */
4000 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4001 return -EUCLEAN;
4002 }
4003 }
4004
4005 w = json_variant_by_key(v, "tpm2-pcrs");
4006 if (!w)
4007 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
4008
4009 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
4010 if (r < 0)
4011 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
4012
4013 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4014 * to SHA256. */
4015 w = json_variant_by_key(v, "tpm2-pcr-bank");
4016 if (w) {
4017 /* The PCR bank field is optional */
4018
4019 if (!json_variant_is_string(w))
4020 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
4021
7bfe0a48 4022 r = tpm2_hash_alg_from_string(json_variant_string(w));
fdf6c27c
LP
4023 if (r < 0)
4024 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
4025
4026 pcr_bank = r;
4027 }
4028
4029 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4030 * the algorithm was hardcoded to ECC. */
4031 w = json_variant_by_key(v, "tpm2-primary-alg");
4032 if (w) {
4033 /* The primary key algorithm is optional */
4034
4035 if (!json_variant_is_string(w))
4036 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
4037
7bfe0a48 4038 r = tpm2_asym_alg_from_string(json_variant_string(w));
fdf6c27c 4039 if (r < 0)
7bfe0a48 4040 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
fdf6c27c
LP
4041
4042 primary_alg = r;
4043 }
4044
4045 w = json_variant_by_key(v, "tpm2-blob");
4046 if (!w)
4047 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
4048
4049 r = json_variant_unbase64(w, &blob, &blob_size);
4050 if (r < 0)
4051 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
4052
4053 w = json_variant_by_key(v, "tpm2-policy-hash");
4054 if (!w)
4055 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4056
4057 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
4058 if (r < 0)
4059 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
4060
4061 w = json_variant_by_key(v, "tpm2-pin");
4062 if (w) {
4063 if (!json_variant_is_boolean(w))
4064 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
4065
4066 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
4067 }
4068
aae6eb96
WR
4069 w = json_variant_by_key(v, "tpm2_salt");
4070 if (w) {
4071 r = json_variant_unbase64(w, &salt, &salt_size);
4072 if (r < 0)
4073 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
4074 }
4075
fdf6c27c
LP
4076 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
4077 if (w) {
4078 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
4079 if (r < 0)
4080 return r;
4081 }
4082
4083 w = json_variant_by_key(v, "tpm2_pubkey");
4084 if (w) {
4085 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
4086 if (r < 0)
4087 return log_debug_errno(r, "Failed to decode PCR public key.");
4088 } else if (pubkey_pcr_mask != 0)
4089 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4090
acbb504e
WR
4091 w = json_variant_by_key(v, "tpm2_srk");
4092 if (w) {
4093 r = json_variant_unbase64(w, &srk_buf, &srk_buf_size);
4094 if (r < 0)
4095 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
4096 }
4097
fdf6c27c
LP
4098 if (ret_keyslot)
4099 *ret_keyslot = keyslot;
4100 if (ret_hash_pcr_mask)
4101 *ret_hash_pcr_mask = hash_pcr_mask;
4102 if (ret_pcr_bank)
4103 *ret_pcr_bank = pcr_bank;
4104 if (ret_pubkey)
4105 *ret_pubkey = TAKE_PTR(pubkey);
4106 if (ret_pubkey_size)
4107 *ret_pubkey_size = pubkey_size;
4108 if (ret_pubkey_pcr_mask)
4109 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
4110 if (ret_primary_alg)
4111 *ret_primary_alg = primary_alg;
4112 if (ret_blob)
4113 *ret_blob = TAKE_PTR(blob);
4114 if (ret_blob_size)
4115 *ret_blob_size = blob_size;
4116 if (ret_policy_hash)
4117 *ret_policy_hash = TAKE_PTR(policy_hash);
4118 if (ret_policy_hash_size)
4119 *ret_policy_hash_size = policy_hash_size;
aae6eb96
WR
4120 if (ret_salt)
4121 *ret_salt = TAKE_PTR(salt);
4122 if (ret_salt_size)
4123 *ret_salt_size = salt_size;
fdf6c27c
LP
4124 if (ret_flags)
4125 *ret_flags = flags;
acbb504e
WR
4126 if (ret_srk_buf)
4127 *ret_srk_buf = TAKE_PTR(srk_buf);
4128 if (ret_srk_buf_size)
4129 *ret_srk_buf_size = srk_buf_size;
fdf6c27c
LP
4130
4131 return 0;
4132}
4133
7bfe0a48
DS
4134const char *tpm2_hash_alg_to_string(uint16_t alg) {
4135 if (alg == TPM2_ALG_SHA1)
07697bfe 4136 return "sha1";
7bfe0a48 4137 if (alg == TPM2_ALG_SHA256)
98193c39 4138 return "sha256";
7bfe0a48 4139 if (alg == TPM2_ALG_SHA384)
98193c39 4140 return "sha384";
7bfe0a48 4141 if (alg == TPM2_ALG_SHA512)
98193c39 4142 return "sha512";
07697bfe
LP
4143 return NULL;
4144}
4145
7bfe0a48
DS
4146int tpm2_hash_alg_from_string(const char *alg) {
4147 if (strcaseeq_ptr(alg, "sha1"))
07697bfe 4148 return TPM2_ALG_SHA1;
7bfe0a48 4149 if (strcaseeq_ptr(alg, "sha256"))
98193c39 4150 return TPM2_ALG_SHA256;
7bfe0a48 4151 if (strcaseeq_ptr(alg, "sha384"))
98193c39 4152 return TPM2_ALG_SHA384;
7bfe0a48 4153 if (strcaseeq_ptr(alg, "sha512"))
98193c39 4154 return TPM2_ALG_SHA512;
07697bfe
LP
4155 return -EINVAL;
4156}
2b92a672 4157
7bfe0a48 4158const char *tpm2_asym_alg_to_string(uint16_t alg) {
2b92a672
LP
4159 if (alg == TPM2_ALG_ECC)
4160 return "ecc";
4161 if (alg == TPM2_ALG_RSA)
4162 return "rsa";
4163 return NULL;
4164}
4165
7bfe0a48 4166int tpm2_asym_alg_from_string(const char *alg) {
f92ebc86 4167 if (strcaseeq_ptr(alg, "ecc"))
2b92a672 4168 return TPM2_ALG_ECC;
f92ebc86 4169 if (strcaseeq_ptr(alg, "rsa"))
2b92a672
LP
4170 return TPM2_ALG_RSA;
4171 return -EINVAL;
4172}
ba578556
LP
4173
4174Tpm2Support tpm2_support(void) {
4175 Tpm2Support support = TPM2_SUPPORT_NONE;
4176 int r;
4177
44d5dd65
LP
4178 if (detect_container() <= 0) {
4179 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
4180 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
4181 * let's assume containers never have a TPM, at least for now. */
4182
db55bbf2 4183 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
44d5dd65
LP
4184 if (r < 0) {
4185 if (r != -ENOENT)
4186 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
4187 } else if (r == 0) /* populated! */
300bba79
DDM
4188 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
4189 else
4190 /* If the directory exists but is empty, we know the subsystem is enabled but no
4191 * driver has been loaded yet. */
4192 support |= TPM2_SUPPORT_SUBSYSTEM;
44d5dd65 4193 }
ba578556
LP
4194
4195 if (efi_has_tpm2())
4196 support |= TPM2_SUPPORT_FIRMWARE;
4197
4198#if HAVE_TPM2
4199 support |= TPM2_SUPPORT_SYSTEM;
33931049
DDM
4200
4201 r = dlopen_tpm2();
4202 if (r >= 0)
4203 support |= TPM2_SUPPORT_LIBRARIES;
ba578556
LP
4204#endif
4205
4206 return support;
4207}
222a951f
LP
4208
4209int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask) {
4210 uint32_t m;
4211 int r;
4212
4213 assert(mask);
4214
4215 /* For use in getopt_long() command line parsers: merges masks specified on the command line */
4216
4217 if (isempty(arg)) {
4218 *mask = 0;
4219 return 0;
4220 }
4221
c69bd0ab 4222 r = tpm2_pcr_mask_from_string(arg, &m);
222a951f
LP
4223 if (r < 0)
4224 return r;
4225
4226 if (*mask == UINT32_MAX)
4227 *mask = m;
4228 else
4229 *mask |= m;
4230
4231 return 0;
4232}
6a0779cb
LP
4233
4234int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
6270b2e6 4235 _cleanup_strv_free_ char **search = NULL;
6a0779cb
LP
4236 _cleanup_free_ char *discovered_path = NULL;
4237 _cleanup_fclose_ FILE *f = NULL;
4238 int r;
4239
4240 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
4241 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4242
6270b2e6
LP
4243 search = strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
4244 if (!search)
4245 return log_oom();
4246
4247 if (!path) {
4248 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
4249 * this case include /.extra/ in the search path, but only in this case, and if we run in the
4250 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
4251
6a0779cb
LP
4252 path = "tpm2-pcr-signature.json";
4253
6270b2e6
LP
4254 if (in_initrd())
4255 if (strv_extend(&search, "/.extra") < 0)
4256 return log_oom();
4257 }
4258
4259 r = search_and_fopen(path, "re", NULL, (const char**) search, &f, &discovered_path);
6a0779cb
LP
4260 if (r < 0)
4261 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
4262
4263 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
4264 if (r < 0)
4265 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
4266
4267 return 0;
4268}
4269
4270int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
4271 _cleanup_free_ char *discovered_path = NULL;
4272 _cleanup_fclose_ FILE *f = NULL;
4273 int r;
4274
4275 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
4276 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4277
4278 if (!path)
4279 path = "tpm2-pcr-public-key.pem";
4280
4281 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
4282 if (r < 0)
4283 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
4284
4285 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
4286 if (r < 0)
4287 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
4288
4289 return 0;
4290}
4d5cc0d4 4291
aae6eb96
WR
4292#define PBKDF2_HMAC_SHA256_ITERATIONS 10000
4293
4294/*
4295 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
4296 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
4297 * I found the wikipedia entry relevant and it contains links to
4298 * relevant RFCs:
4299 * - https://en.wikipedia.org/wiki/PBKDF2
4300 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
4301 */
4302int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
4303 size_t passlen,
4304 const void *salt,
4305 size_t saltlen,
4306 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
4307
4308 uint8_t _cleanup_(erase_and_freep) *buffer = NULL;
4309 uint8_t u[SHA256_DIGEST_SIZE];
4310
4311 /* To keep this simple, since derived KeyLen (dkLen in docs)
4312 * Is the same as the hash output, we don't need multiple
4313 * blocks. Part of the algorithm is to add the block count
4314 * in, but this can be hardcoded to 1.
4315 */
4316 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
4317
504d0acf 4318 assert (salt);
aae6eb96
WR
4319 assert (saltlen > 0);
4320 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
4321 assert (passlen > 0);
4322
4323 /*
4324 * Build a buffer of salt + block_cnt and hmac_sha256 it we
4325 * do this as we don't have a context builder for HMAC_SHA256.
4326 */
4327 buffer = malloc(saltlen + sizeof(block_cnt));
4328 if (!buffer)
4329 return -ENOMEM;
4330
4331 memcpy(buffer, salt, saltlen);
4332 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
4333
4334 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
4335
4336 /* dk needs to be an unmodified u as u gets modified in the loop */
4337 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
4338 uint8_t *dk = ret_key;
4339
4340 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
4341 hmac_sha256(pass, passlen, u, sizeof(u), u);
4342
4343 for (size_t j=0; j < sizeof(u); j++)
4344 dk[j] ^= u[j];
4345 }
4346
4347 return 0;
4348}
96ead603
OJ
4349
4350static const char* const pcr_index_table[_PCR_INDEX_MAX_DEFINED] = {
4351 [PCR_PLATFORM_CODE] = "platform-code",
4352 [PCR_PLATFORM_CONFIG] = "platform-config",
4353 [PCR_EXTERNAL_CODE] = "external-code",
4354 [PCR_EXTERNAL_CONFIG] = "external-config",
4355 [PCR_BOOT_LOADER_CODE] = "boot-loader-code",
4356 [PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
4357 [PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
4358 [PCR_KERNEL_INITRD] = "kernel-initrd",
4359 [PCR_IMA] = "ima",
4360 [PCR_KERNEL_BOOT] = "kernel-boot",
4361 [PCR_KERNEL_CONFIG] = "kernel-config",
4362 [PCR_SYSEXTS] = "sysexts",
4363 [PCR_SHIM_POLICY] = "shim-policy",
4364 [PCR_SYSTEM_IDENTITY] = "system-identity",
4365 [PCR_DEBUG] = "debug",
4366 [PCR_APPLICATION_SUPPORT] = "application-support",
4367};
4368
d685a5f6 4369DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(pcr_index, int, TPM2_PCRS_MAX - 1);
f70c90f5 4370DEFINE_STRING_TABLE_LOOKUP_TO_STRING(pcr_index, int);