]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/tpm2-util.c
tpm2: remove all extern tpm2-tss symbols
[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"
acbb504e 16#include "lock-util.h"
a12bc99e
ZJS
17#include "log.h"
18#include "logarithm.h"
5e521624 19#include "memory-util.h"
d9b5841d 20#include "openssl-util.h"
fdf6c27c 21#include "parse-util.h"
5e521624 22#include "random-util.h"
2f5a892a 23#include "sha256.h"
fdf6c27c 24#include "stat-util.h"
96ead603 25#include "string-table.h"
5e521624 26#include "time-util.h"
fdf6c27c
LP
27#include "tpm2-util.h"
28#include "virt.h"
5e521624 29
fdf6c27c 30#if HAVE_TPM2
5e521624
LP
31static void *libtss2_esys_dl = NULL;
32static void *libtss2_rc_dl = NULL;
33static void *libtss2_mu_dl = NULL;
34
b57a7b3d
DS
35static 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;
36static 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;
37static 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;
38static void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
39static TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
40static void (*sym_Esys_Free)(void *ptr) = NULL;
41static 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;
42static TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
43static TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
44static 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;
45static 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;
46static 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;
47static 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;
48static 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;
49static TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
50static TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
51static 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;
52static 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;
53static 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;
54static TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
55static TSS2_RC (*sym_Esys_TRSess_GetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION *flags) = NULL;
56static TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask) = NULL;
57static TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name) = NULL;
58static TSS2_RC (*sym_Esys_TR_Deserialize)(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle) = NULL;
59static 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;
60static TSS2_RC (*sym_Esys_TR_Serialize)(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size) = NULL;
61static TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
62static 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;
63static 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;
64
65static const char* (*sym_Tss2_RC_Decode)(static TSS2_RC rc) = NULL;
66
67static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal)(TPM2_CC src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
68static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
69static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
70static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
71static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
72static 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;
73static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal)(TPMT_HA const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
74static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal)(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
5e521624
LP
75
76int dlopen_tpm2(void) {
d32f7a8e
ZJS
77 int r;
78
79 r = dlopen_many_sym_or_warn(
80 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
81 DLSYM_ARG(Esys_Create),
82 DLSYM_ARG(Esys_CreatePrimary),
acbb504e 83 DLSYM_ARG(Esys_EvictControl),
d32f7a8e
ZJS
84 DLSYM_ARG(Esys_Finalize),
85 DLSYM_ARG(Esys_FlushContext),
86 DLSYM_ARG(Esys_Free),
07697bfe 87 DLSYM_ARG(Esys_GetCapability),
d32f7a8e
ZJS
88 DLSYM_ARG(Esys_GetRandom),
89 DLSYM_ARG(Esys_Initialize),
90 DLSYM_ARG(Esys_Load),
0d756413 91 DLSYM_ARG(Esys_LoadExternal),
1421943a 92 DLSYM_ARG(Esys_PCR_Extend),
321a9d9e 93 DLSYM_ARG(Esys_PCR_Read),
0d756413 94 DLSYM_ARG(Esys_PolicyAuthorize),
2f5a892a 95 DLSYM_ARG(Esys_PolicyAuthValue),
d32f7a8e
ZJS
96 DLSYM_ARG(Esys_PolicyGetDigest),
97 DLSYM_ARG(Esys_PolicyPCR),
acbb504e 98 DLSYM_ARG(Esys_ReadPublic),
d32f7a8e
ZJS
99 DLSYM_ARG(Esys_StartAuthSession),
100 DLSYM_ARG(Esys_Startup),
e976445d 101 DLSYM_ARG(Esys_TRSess_GetAttributes),
da29de23 102 DLSYM_ARG(Esys_TRSess_SetAttributes),
acbb504e 103 DLSYM_ARG(Esys_TR_FromTPMPublic),
0d756413 104 DLSYM_ARG(Esys_TR_GetName),
acbb504e
WR
105 DLSYM_ARG(Esys_TR_Deserialize),
106 DLSYM_ARG(Esys_TR_Serialize),
2f5a892a 107 DLSYM_ARG(Esys_TR_SetAuth),
0d756413
LP
108 DLSYM_ARG(Esys_Unseal),
109 DLSYM_ARG(Esys_VerifySignature));
d32f7a8e
ZJS
110 if (r < 0)
111 return r;
112
113 r = dlopen_many_sym_or_warn(
114 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
115 DLSYM_ARG(Tss2_RC_Decode));
116 if (r < 0)
117 return r;
118
119 return dlopen_many_sym_or_warn(
120 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
dcbc4674 121 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
d32f7a8e
ZJS
122 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
123 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
124 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
dbae4b95 125 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
dcbc4674 126 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal),
dbae4b95
DS
127 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal),
128 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal));
5e521624
LP
129}
130
b57a7b3d
DS
131static inline void Esys_Freep(void *p) {
132 if (*(void**) p)
133 sym_Esys_Free(*(void**) p);
134}
135
68d084ce
DS
136static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
137 if (!c)
138 return NULL;
5e521624
LP
139
140 if (c->esys_context)
141 sym_Esys_Finalize(&c->esys_context);
142
143 c->tcti_context = mfree(c->tcti_context);
f2592ef0 144 c->tcti_dl = safe_dlclose(c->tcti_dl);
5e521624 145
68d084ce 146 return mfree(c);
5e521624
LP
147}
148
68d084ce
DS
149DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
150
68d084ce
DS
151int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
152 _cleanup_tpm2_context_ Tpm2Context *context = NULL;
5e521624
LP
153 TSS2_RC rc;
154 int r;
155
68d084ce
DS
156 assert(ret_context);
157
d70e4bc9 158 context = new(Tpm2Context, 1);
68d084ce
DS
159 if (!context)
160 return log_oom();
161
d70e4bc9
LP
162 *context = (Tpm2Context) {
163 .n_ref = 1,
164 };
68d084ce 165
5e521624
LP
166 r = dlopen_tpm2();
167 if (r < 0)
168 return log_error_errno(r, "TPM2 support not installed: %m");
169
34906680 170 if (!device) {
5e521624 171 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
34906680
LP
172 if (device)
173 /* Setting the env var to an empty string forces tpm2-tss' own device picking
174 * logic to be used. */
175 device = empty_to_null(device);
176 else
177 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
178 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
179 * might be used and we really don't want that, since it is a system service and that creates
180 * various ordering issues/deadlocks during early boot. */
181 device = "device:/dev/tpmrm0";
182 }
5e521624
LP
183
184 if (device) {
185 const char *param, *driver, *fn;
186 const TSS2_TCTI_INFO* info;
187 TSS2_TCTI_INFO_FUNC func;
188 size_t sz = 0;
189
190 param = strchr(device, ':');
191 if (param) {
50a08514 192 /* Syntax #1: Pair of driver string and arbitrary parameter */
2f82562b 193 driver = strndupa_safe(device, param - device);
50a08514
LP
194 if (isempty(driver))
195 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
196
5e521624 197 param++;
50a08514
LP
198 } else if (path_is_absolute(device) && path_is_valid(device)) {
199 /* Syntax #2: TPM device node */
5e521624
LP
200 driver = "device";
201 param = device;
50a08514
LP
202 } else
203 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
204
205 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
5e521624
LP
206
207 fn = strjoina("libtss2-tcti-", driver, ".so.0");
208
50a08514
LP
209 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
210 if (!filename_is_valid(fn))
211 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
212
68d084ce
DS
213 context->tcti_dl = dlopen(fn, RTLD_NOW);
214 if (!context->tcti_dl)
5e521624
LP
215 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
216
68d084ce 217 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
5e521624
LP
218 if (!func)
219 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
220 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
221 dlerror());
222
223 info = func();
224 if (!info)
225 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
226
5e521624
LP
227 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
228
229 rc = info->init(NULL, &sz, NULL);
230 if (rc != TPM2_RC_SUCCESS)
231 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
232 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
233
68d084ce
DS
234 context->tcti_context = malloc0(sz);
235 if (!context->tcti_context)
5e521624
LP
236 return log_oom();
237
68d084ce 238 rc = info->init(context->tcti_context, &sz, param);
5e521624
LP
239 if (rc != TPM2_RC_SUCCESS)
240 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
241 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
242 }
243
68d084ce 244 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
5e521624
LP
245 if (rc != TSS2_RC_SUCCESS)
246 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
247 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
248
68d084ce 249 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
5e521624
LP
250 if (rc == TPM2_RC_INITIALIZE)
251 log_debug("TPM already started up.");
252 else if (rc == TSS2_RC_SUCCESS)
253 log_debug("TPM successfully started up.");
254 else
255 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
256 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
257
68d084ce 258 *ret_context = TAKE_PTR(context);
5e521624
LP
259
260 return 0;
261}
262
16e16b8c
DS
263static void tpm2_handle_flush(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle) {
264 if (!esys_context || esys_handle == ESYS_TR_NONE)
265 return;
266
267 TSS2_RC rc = sym_Esys_FlushContext(esys_context, esys_handle);
268 if (rc != TSS2_RC_SUCCESS) /* We ignore failures here (besides debug logging), since this is called
269 * in error paths, where we cannot do anything about failures anymore. And
270 * when it is called in successful codepaths by this time we already did
271 * what we wanted to do, and got the results we wanted so there's no
272 * reason to make this fail more loudly than necessary. */
273 log_debug("Failed to flush TPM handle, ignoring: %s", sym_Tss2_RC_Decode(rc));
274}
275
276Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
277 if (!handle)
278 return NULL;
279
280 _cleanup_tpm2_context_ Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
acbb504e 281 if (context && !handle->keep)
16e16b8c
DS
282 tpm2_handle_flush(context->esys_context, handle->esys_handle);
283
284 return mfree(handle);
285}
286
287int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
288 _cleanup_tpm2_handle_ Tpm2Handle *handle = NULL;
289
290 assert(ret_handle);
291
d70e4bc9 292 handle = new(Tpm2Handle, 1);
16e16b8c
DS
293 if (!handle)
294 return log_oom();
295
d70e4bc9
LP
296 *handle = (Tpm2Handle) {
297 .tpm2_context = tpm2_context_ref(context),
298 .esys_handle = ESYS_TR_NONE,
299 };
16e16b8c
DS
300
301 *ret_handle = TAKE_PTR(handle);
302
303 return 0;
304}
305
aba5dac3
LP
306#define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
307
23e9ccc2 308static int tpm2_credit_random(Tpm2Context *c) {
5e521624
LP
309 size_t rps, done = 0;
310 TSS2_RC rc;
aba5dac3 311 usec_t t;
5e521624
LP
312 int r;
313
314 assert(c);
315
316 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
317 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
318 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
319 * any entropy. */
320
aba5dac3
LP
321 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
322 if (errno != ENOENT)
323 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
324 } else {
325 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
326 return 0; /* Already done */
327 }
328
329 t = now(CLOCK_MONOTONIC);
330
5e521624
LP
331 for (rps = random_pool_size(); rps > 0;) {
332 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
333
334 rc = sym_Esys_GetRandom(
23e9ccc2 335 c->esys_context,
5e521624
LP
336 ESYS_TR_NONE,
337 ESYS_TR_NONE,
338 ESYS_TR_NONE,
339 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
340 &buffer);
341 if (rc != TSS2_RC_SUCCESS)
342 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
343 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
344
345 if (buffer->size == 0)
346 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
347 "Zero-sized entropy returned from TPM.");
348
aba5dac3 349 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
5e521624
LP
350 if (r < 0)
351 return log_error_errno(r, "Failed wo write entropy to kernel: %m");
352
353 done += buffer->size;
354 rps = LESS_BY(rps, buffer->size);
355 }
356
aba5dac3
LP
357 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
358
359 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
360 if (r < 0)
361 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
362
5e521624
LP
363 return 0;
364}
365
acbb504e 366const TPM2B_PUBLIC *tpm2_get_primary_template(Tpm2SRKTemplateFlags flags) {
5e521624 367
acbb504e
WR
368 /*
369 * Set up array so flags can be used directly as an input.
370 *
371 * Templates for SRK come from the spec:
372 * - https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf
373 *
374 * However, note their is some lore here. On Linux, the SRK has it's unique field set to size 0 and
375 * on Windows the SRK has their unique data set to keyLen in bytes of zeros.
376 */
377 assert(flags >= 0);
378 assert(flags <= _TPM2_SRK_TEMPLATE_MAX);
379
380 static const TPM2B_PUBLIC templ[_TPM2_SRK_TEMPLATE_MAX + 1] = {
381 /* index 0 RSA old */
382 [0] = {
383 .publicArea = {
384 .type = TPM2_ALG_RSA,
385 .nameAlg = TPM2_ALG_SHA256,
386 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
387 .parameters.rsaDetail = {
388 .symmetric = {
389 .algorithm = TPM2_ALG_AES,
390 .keyBits.aes = 128,
391 .mode.aes = TPM2_ALG_CFB,
392 },
393 .scheme.scheme = TPM2_ALG_NULL,
394 .keyBits = 2048,
5e521624
LP
395 },
396 },
397 },
acbb504e
WR
398 [TPM2_SRK_TEMPLATE_ECC] = {
399 .publicArea = {
400 .type = TPM2_ALG_ECC,
401 .nameAlg = TPM2_ALG_SHA256,
402 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
403 .parameters.eccDetail = {
404 .symmetric = {
405 .algorithm = TPM2_ALG_AES,
406 .keyBits.aes = 128,
407 .mode.aes = TPM2_ALG_CFB,
408 },
409 .scheme.scheme = TPM2_ALG_NULL,
410 .curveID = TPM2_ECC_NIST_P256,
411 .kdf.scheme = TPM2_ALG_NULL,
412 },
413 },
414 },
415 [TPM2_SRK_TEMPLATE_NEW_STYLE] = {
416 .publicArea = {
417 .type = TPM2_ALG_RSA,
418 .nameAlg = TPM2_ALG_SHA256,
419 .objectAttributes = TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_USERWITHAUTH|TPMA_OBJECT_NODA,
420 .parameters.rsaDetail = {
421 .symmetric = {
422 .algorithm = TPM2_ALG_AES,
423 .keyBits.aes = 128,
424 .mode.aes = TPM2_ALG_CFB,
425 },
426 .scheme.scheme = TPM2_ALG_NULL,
427 .keyBits = 2048,
428 },
429 },
430 },
431 [TPM2_SRK_TEMPLATE_NEW_STYLE|TPM2_SRK_TEMPLATE_ECC] = {
432 .publicArea = {
433 .type = TPM2_ALG_ECC,
434 .nameAlg = TPM2_ALG_SHA256,
435 .objectAttributes = TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_USERWITHAUTH|TPMA_OBJECT_NODA,
436 .parameters.eccDetail = {
437 .symmetric = {
438 .algorithm = TPM2_ALG_AES,
439 .keyBits.aes = 128,
440 .mode.aes = TPM2_ALG_CFB,
441 },
442 .scheme.scheme = TPM2_ALG_NULL,
443 .curveID = TPM2_ECC_NIST_P256,
444 .kdf.scheme = TPM2_ALG_NULL,
2b92a672
LP
445 },
446 },
447 },
448 };
449
acbb504e
WR
450 return &templ[flags];
451}
452
453/*
454 * Why and what is an SRK?
455 * TL;DR provides a working space for those without owner auth. The user enrolling
456 * the disk may not have access to the TPMs owner hierarchy auth, so they need a
457 * working space. This working space is at the defined address of 0x81000001.
458 * Details can be found here:
459 * - https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf
460 */
461#define SRK_HANDLE UINT32_C(0x81000001)
462
463/*
464 * Retrieves the SRK handle if present. Returns 0 if SRK not present, 1 if present
465 * and < 0 on error
466 */
467static int tpm2_get_srk(
468 Tpm2Context *c,
469 TPMI_ALG_PUBLIC *ret_alg,
470 Tpm2Handle *ret_primary) {
471
472 TPMI_YES_NO more_data;
473 ESYS_TR primary_tr = ESYS_TR_NONE;
474 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *cap_data = NULL;
475
476 assert(c);
477 assert(ret_primary);
478
479 TSS2_RC rc = sym_Esys_GetCapability(c->esys_context,
480 ESYS_TR_NONE,
481 ESYS_TR_NONE,
482 ESYS_TR_NONE,
483 TPM2_CAP_HANDLES,
484 SRK_HANDLE,
485 1,
486 &more_data,
487 &cap_data);
488 if (rc != TSS2_RC_SUCCESS)
489 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
490 "Failed to enumerate handles searching for SRK: %s",
491 sym_Tss2_RC_Decode(rc));
492
493 /* Did Not find SRK, indicate this by returning 0 */
494 if (cap_data->data.handles.count == 0 || cap_data->data.handles.handle[0] != SRK_HANDLE) {
495 ret_primary->esys_handle = ESYS_TR_NONE;
496
497 if (ret_alg)
498 *ret_alg = 0;
499 return 0;
500 }
501
502 log_debug("Found SRK on TPM.");
503
504 /* convert the raw handle to an ESYS_TR */
505 TPM2_HANDLE handle = cap_data->data.handles.handle[0];
506 rc = sym_Esys_TR_FromTPMPublic(c->esys_context,
507 handle,
508 ESYS_TR_NONE,
509 ESYS_TR_NONE,
510 ESYS_TR_NONE,
511 &primary_tr);
512 if (rc != TSS2_RC_SUCCESS)
513 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
514 "Failed to convert ray handle to ESYS_TR for SRK: %s",
515 sym_Tss2_RC_Decode(rc));
516
517 /* Get the algorithm if the caller wants it */
518 _cleanup_(Esys_Freep) TPM2B_PUBLIC *out_public = NULL;
519 if (ret_alg) {
520 rc = sym_Esys_ReadPublic(
521 c->esys_context,
522 primary_tr,
523 ESYS_TR_NONE,
524 ESYS_TR_NONE,
525 ESYS_TR_NONE,
526 &out_public,
527 NULL,
528 NULL);
529 if (rc != TSS2_RC_SUCCESS)
530 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
531 "Failed to convert ray handle to ESYS_TR for SRK: %s",
532 sym_Tss2_RC_Decode(rc));
533 }
534
535 ret_primary->esys_handle = primary_tr;
536
537 if (ret_alg)
538 *ret_alg = out_public->publicArea.type;
539
540 return 1;
541}
542
543static int tpm2_make_primary(
544 Tpm2Context *c,
545 TPMI_ALG_PUBLIC alg,
546 bool use_srk_model,
547 TPMI_ALG_PUBLIC *ret_alg,
548 Tpm2Handle **ret_primary) {
549
550 static const TPM2B_SENSITIVE_CREATE primary_sensitive = {};
5e521624 551 static const TPML_PCR_SELECTION creation_pcr = {};
acbb504e
WR
552 const TPM2B_PUBLIC *primary_template = NULL;
553 Tpm2SRKTemplateFlags base_flags = use_srk_model ? TPM2_SRK_TEMPLATE_NEW_STYLE : 0;
554 _cleanup_(release_lock_file) LockFile srk_lock = LOCK_FILE_INIT;
5e521624 555 TSS2_RC rc;
2b92a672 556 usec_t ts;
16e16b8c 557 int r;
5e521624 558
acbb504e 559 log_debug("Creating %s on TPM.", use_srk_model ? "SRK" : "Transient Primary Key");
5e521624 560
2b92a672
LP
561 /* So apparently not all TPM2 devices support ECC. ECC is generally preferably, because it's so much
562 * faster, noticeably so (~10s vs. ~240ms on my system). Hence, unless explicitly configured let's
563 * try to use ECC first, and if that does not work, let's fall back to RSA. */
5e521624 564
2b92a672
LP
565 ts = now(CLOCK_MONOTONIC);
566
16e16b8c
DS
567 _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
568 r = tpm2_handle_new(c, &primary);
569 if (r < 0)
570 return r;
571
acbb504e
WR
572 /* we only need the SRK lock when making the SRK since its not atomic, transient
573 * primary creations don't even matter if they stomp on each other, the TPM will
574 * keep kicking back the same key.
575 */
576 if (use_srk_model) {
577 r = make_lock_file("/run/systemd/tpm2-srk-init", LOCK_EX, &srk_lock);
578 if (r < 0)
96181b7a 579 return log_error_errno(r, "Failed to take TPM SRK lock: %m");
acbb504e
WR
580 }
581
582 /* Find existing SRK and use it if present */
583 if (use_srk_model) {
584 TPMI_ALG_PUBLIC got_alg = TPM2_ALG_NULL;
585 r = tpm2_get_srk(c, &got_alg, primary);
586 if (r < 0)
587 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
588 "Failed to establish if SRK is present");
589 if (r == 1) {
590 log_debug("Discovered existing SRK");
591
592 if (alg != 0 && alg != got_alg)
593 log_warning("Caller asked for specific algorithm %u, but existing SRK is %u, ignoring",
96181b7a 594 alg, got_alg);
acbb504e
WR
595
596 if (ret_alg)
597 *ret_alg = alg;
598 if (ret_primary)
599 *ret_primary = TAKE_PTR(primary);
600 return 0;
601 }
602 log_debug("Did not find SRK, generating...");
603 }
604
2b92a672 605 if (IN_SET(alg, 0, TPM2_ALG_ECC)) {
acbb504e
WR
606 primary_template = tpm2_get_primary_template(base_flags | TPM2_SRK_TEMPLATE_ECC);
607
2b92a672 608 rc = sym_Esys_CreatePrimary(
23e9ccc2 609 c->esys_context,
2b92a672
LP
610 ESYS_TR_RH_OWNER,
611 ESYS_TR_PASSWORD,
612 ESYS_TR_NONE,
613 ESYS_TR_NONE,
614 &primary_sensitive,
acbb504e 615 primary_template,
2b92a672
LP
616 NULL,
617 &creation_pcr,
16e16b8c 618 &primary->esys_handle,
2b92a672
LP
619 NULL,
620 NULL,
621 NULL,
622 NULL);
623
624 if (rc != TSS2_RC_SUCCESS) {
625 if (alg != 0)
626 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
627 "Failed to generate ECC primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
628
629 log_debug("Failed to generate ECC primary key in TPM, trying RSA: %s", sym_Tss2_RC_Decode(rc));
630 } else {
631 log_debug("Successfully created ECC primary key on TPM.");
632 alg = TPM2_ALG_ECC;
633 }
634 }
635
636 if (IN_SET(alg, 0, TPM2_ALG_RSA)) {
acbb504e
WR
637 primary_template = tpm2_get_primary_template(base_flags);
638
2b92a672 639 rc = sym_Esys_CreatePrimary(
23e9ccc2 640 c->esys_context,
2b92a672
LP
641 ESYS_TR_RH_OWNER,
642 ESYS_TR_PASSWORD,
643 ESYS_TR_NONE,
644 ESYS_TR_NONE,
645 &primary_sensitive,
acbb504e 646 primary_template,
2b92a672
LP
647 NULL,
648 &creation_pcr,
16e16b8c 649 &primary->esys_handle,
2b92a672
LP
650 NULL,
651 NULL,
652 NULL,
653 NULL);
654 if (rc != TSS2_RC_SUCCESS)
655 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
656 "Failed to generate RSA primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
657 else if (alg == 0) {
658 log_notice("TPM2 chip apparently does not support ECC primary keys, falling back to RSA. "
659 "This likely means TPM2 operations will be relatively slow, please be patient.");
660 alg = TPM2_ALG_RSA;
661 }
662
663 log_debug("Successfully created RSA primary key on TPM.");
664 }
5e521624 665
acbb504e
WR
666 log_debug("Generating %s on the TPM2 took %s.", use_srk_model ? "SRK" : "Transient Primary Key",
667 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
668
669 if (use_srk_model) {
670 rc = sym_Esys_EvictControl(c->esys_context, ESYS_TR_RH_OWNER, primary->esys_handle,
671 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, SRK_HANDLE, &primary->esys_handle);
672 if (rc != TSS2_RC_SUCCESS)
673 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
674 "Failed to persist SRK within TPM: %s", sym_Tss2_RC_Decode(rc));
675 primary->keep = true;
676 }
5e521624 677
16e16b8c
DS
678 if (ret_primary)
679 *ret_primary = TAKE_PTR(primary);
2b92a672
LP
680 if (ret_alg)
681 *ret_alg = alg;
682
5e521624
LP
683 return 0;
684}
685
c69bd0ab
DS
686/* Utility functions for TPMS_PCR_SELECTION. */
687
688/* Convert a TPMS_PCR_SELECTION object to a mask. */
689void tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s, uint32_t *ret) {
690 assert(s);
691 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
321a9d9e
LP
692 assert(ret);
693
c69bd0ab
DS
694 uint32_t mask = 0;
695 for (unsigned i = 0; i < s->sizeofSelect; i++)
696 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
697 *ret = mask;
698}
321a9d9e 699
c69bd0ab
DS
700/* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
701void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
702 assert(ret);
703
704 /* This is currently hardcoded at 24 PCRs, above. */
705 if (!TPM2_PCR_MASK_VALID(mask))
706 log_warning("PCR mask selections (%x) out of range, ignoring.",
707 mask & ~((uint32_t)TPM2_PCRS_MASK));
708
709 *ret = (TPMS_PCR_SELECTION){
710 .hash = hash_alg,
711 .sizeofSelect = TPM2_PCRS_MAX / 8,
712 .pcrSelect[0] = mask & 0xff,
713 .pcrSelect[1] = (mask >> 8) & 0xff,
714 .pcrSelect[2] = (mask >> 16) & 0xff,
715 };
716}
717
718/* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
719void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
720 assert(a);
721 assert(b);
722 assert(a->hash == b->hash);
723
724 uint32_t maska, maskb;
725 tpm2_tpms_pcr_selection_to_mask(a, &maska);
726 tpm2_tpms_pcr_selection_to_mask(b, &maskb);
727 tpm2_tpms_pcr_selection_from_mask(maska | maskb, a->hash, a);
728}
729
730/* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
731void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
732 assert(a);
733 assert(b);
734 assert(a->hash == b->hash);
735
736 uint32_t maska, maskb;
737 tpm2_tpms_pcr_selection_to_mask(a, &maska);
738 tpm2_tpms_pcr_selection_to_mask(b, &maskb);
739 tpm2_tpms_pcr_selection_from_mask(maska & ~maskb, a->hash, a);
740}
741
742/* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
743void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
744 if (a == b)
745 return;
746
747 tpm2_tpms_pcr_selection_add(a, b);
748 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
749}
750
751#define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
752 _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, UNIQ)
753#define _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, uniq) \
754 FOREACH_PCR_IN_MASK(pcr, \
755 ({ uint32_t UNIQ_T(_mask, uniq); \
756 tpm2_tpms_pcr_selection_to_mask(tpms, &UNIQ_T(_mask, uniq)); \
757 UNIQ_T(_mask, uniq); \
758 }))
759
760#define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
761 UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ)
762#define UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, uniq) \
763 for (TPML_PCR_SELECTION *UNIQ_T(_tpml, uniq) = (TPML_PCR_SELECTION*)(tpml); \
764 UNIQ_T(_tpml, uniq); UNIQ_T(_tpml, uniq) = NULL) \
765 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, UNIQ_T(_tpml, uniq))
766#define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
767 for (TPMS_PCR_SELECTION *tpms = tpml->pcrSelections; \
768 (uint32_t)(tpms - tpml->pcrSelections) < tpml->count; \
769 tpms++)
770
771#define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
772 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
773 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
774
775char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
776 assert(s);
777
778 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
779
780 uint32_t mask;
781 tpm2_tpms_pcr_selection_to_mask(s, &mask);
782 _cleanup_free_ char *maskstr = tpm2_pcr_mask_to_string(mask);
783 if (!maskstr)
784 return NULL;
785
786 return strjoin(algstr, "(", maskstr, ")");
787}
788
789size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
790 assert(s);
791
792 uint32_t mask;
793 tpm2_tpms_pcr_selection_to_mask(s, &mask);
a12bc99e 794 return popcount(mask);
c69bd0ab
DS
795}
796
797/* Utility functions for TPML_PCR_SELECTION. */
798
799/* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
800static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
801 assert(l);
802 assert(l->count <= sizeof(l->pcrSelections));
803 assert(index < l->count);
804
805 size_t s = l->count - (index + 1);
806 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
807 l->count--;
808}
809
810/* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
811 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
812 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
813static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
814 TPML_PCR_SELECTION *l,
815 TPMI_ALG_HASH hash_alg) {
816
817 assert(l);
818
819 TPMS_PCR_SELECTION *selection = NULL;
820 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
821 if (s->hash == hash_alg) {
822 selection = s;
823 break;
824 }
825
826 if (!selection)
827 return NULL;
828
829 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
830 for (uint32_t i = l->count - 1; i > 0; i--) {
831 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
832
833 if (selection == s)
834 break;
835
836 if (s->hash == hash_alg) {
837 tpm2_tpms_pcr_selection_move(selection, s);
838 tpm2_tpml_pcr_selection_remove_index(l, i);
4dde902e 839 }
c69bd0ab
DS
840 }
841
842 return selection;
843}
844
845/* Convert a TPML_PCR_SELECTION object to a mask. Returns -ENOENT if 'hash_alg' is not in the object. */
846int tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg, uint32_t *ret) {
847 assert(l);
848 assert(ret);
849
850 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
851 * are multiple entries with the requested hash alg. */
852 TPML_PCR_SELECTION lcopy = *l;
853
854 TPMS_PCR_SELECTION *s;
855 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
856 if (!s)
857 return SYNTHETIC_ERRNO(ENOENT);
858
859 tpm2_tpms_pcr_selection_to_mask(s, ret);
860 return 0;
861}
862
863/* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
864void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
865 assert(ret);
866
867 TPMS_PCR_SELECTION s;
868 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
869
870 *ret = (TPML_PCR_SELECTION){
871 .count = 1,
872 .pcrSelections[0] = s,
321a9d9e
LP
873 };
874}
875
c69bd0ab
DS
876/* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
877static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
878 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
879 /* This removes all duplicates for s->hash. */
880 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
881}
882
883/* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
884 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
885 * entries with the same hash alg. */
886void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
887 assert(l);
888 assert(s);
889
890 if (tpm2_tpms_pcr_selection_is_empty(s))
891 return;
892
893 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
894 if (selection) {
895 tpm2_tpms_pcr_selection_add(selection, s);
896 return;
897 }
898
899 /* It's already broken if the count is higher than the array has size for. */
900 assert(!(l->count > sizeof(l->pcrSelections)));
901
902 /* If full, the cleanup should result in at least one available entry. */
903 if (l->count == sizeof(l->pcrSelections))
904 tpm2_tpml_pcr_selection_cleanup(l);
905
906 assert(l->count < sizeof(l->pcrSelections));
907 l->pcrSelections[l->count++] = *s;
908}
909
910/* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
911 * will combine all entries for 's->hash' in 'l'. */
912void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
913 assert(l);
914 assert(s);
915
916 if (tpm2_tpms_pcr_selection_is_empty(s))
917 return;
918
919 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
920 if (selection)
921 tpm2_tpms_pcr_selection_sub(selection, s);
922}
923
924/* Add all PCR selections in 'b' to 'a'. */
925void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
926 assert(a);
927 assert(b);
928
929 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
930 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
931}
932
933/* Remove all PCR selections in 'b' from 'a'. */
934void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
935 assert(a);
936 assert(b);
937
938 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
939 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
940}
941
942char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
943 assert(l);
944
945 _cleanup_free_ char *banks = NULL;
946 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, (TPML_PCR_SELECTION*) l) {
947 if (tpm2_tpms_pcr_selection_is_empty(s))
948 continue;
949
950 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
951 if (!str || !strextend_with_separator(&banks, ",", str))
952 return NULL;
953 }
954
955 return strjoin("[", strempty(banks), "]");
956}
957
958size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
959 assert(l);
960 assert(l->count <= sizeof(l->pcrSelections));
961
962 size_t weight = 0;
963 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
964 size_t w = tpm2_tpms_pcr_selection_weight(s);
965 assert(weight <= SIZE_MAX - w);
966 weight += w;
967 }
968
969 return weight;
970}
971
c57d8bc8
DS
972static void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
973 if (!DEBUG_LOGGING || !l)
974 return;
975
976 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
977 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
978}
979
23b972d5
DS
980static void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
981 if (!DEBUG_LOGGING || !buffer || size == 0)
982 return;
983
984 _cleanup_free_ char *h = hexmem(buffer, size);
985 log_debug("%s: %s", msg ?: "Buffer", strna(h));
986}
987
988static void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
989 if (digest)
990 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
991}
992
dbae4b95
DS
993static void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
994 if (name)
995 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
996}
997
23b972d5
DS
998static int tpm2_get_policy_digest(
999 Tpm2Context *c,
1000 const Tpm2Handle *session,
1001 TPM2B_DIGEST **ret_policy_digest) {
1002
1003 TSS2_RC rc;
1004
1005 if (!DEBUG_LOGGING && !ret_policy_digest)
1006 return 0;
1007
1008 assert(c);
1009 assert(session);
1010
1011 log_debug("Acquiring policy digest.");
1012
1013 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1014 rc = sym_Esys_PolicyGetDigest(
1015 c->esys_context,
1016 session->esys_handle,
1017 ESYS_TR_NONE,
1018 ESYS_TR_NONE,
1019 ESYS_TR_NONE,
1020 &policy_digest);
1021 if (rc != TSS2_RC_SUCCESS)
1022 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1023 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1024
1025 tpm2_log_debug_digest(policy_digest, "Session policy digest");
1026
1027 if (ret_policy_digest)
1028 *ret_policy_digest = TAKE_PTR(policy_digest);
1029
1030 return 0;
1031}
1032
c57d8bc8
DS
1033static int tpm2_pcr_read(
1034 Tpm2Context *c,
1035 const TPML_PCR_SELECTION *pcr_selection,
1036 TPML_PCR_SELECTION *ret_pcr_selection,
1037 TPM2B_DIGEST **ret_pcr_values,
c648a4b8 1038 size_t *ret_n_pcr_values) {
c57d8bc8
DS
1039
1040 _cleanup_free_ TPM2B_DIGEST *pcr_values = NULL;
1041 TPML_PCR_SELECTION remaining, total_read = {};
c648a4b8 1042 size_t n_pcr_values = 0;
c57d8bc8 1043 TSS2_RC rc;
321a9d9e 1044
c57d8bc8
DS
1045 assert(c);
1046 assert(pcr_selection);
321a9d9e 1047
c57d8bc8
DS
1048 remaining = *pcr_selection;
1049 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
1050 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
1051 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
321a9d9e 1052
c57d8bc8 1053 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
321a9d9e 1054
c57d8bc8
DS
1055 /* Unfortunately, PCR_Read will not return more than 8 values. */
1056 rc = sym_Esys_PCR_Read(
1057 c->esys_context,
1058 ESYS_TR_NONE,
1059 ESYS_TR_NONE,
1060 ESYS_TR_NONE,
1061 &remaining,
1062 NULL,
1063 &current_read,
1064 &current_values);
1065 if (rc != TSS2_RC_SUCCESS)
1066 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1067 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
321a9d9e 1068
c57d8bc8
DS
1069 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
1070 log_warning("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
1071 break;
321a9d9e
LP
1072 }
1073
c57d8bc8
DS
1074 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
1075 tpm2_tpml_pcr_selection_add(&total_read, current_read);
1076
c648a4b8 1077 if (!GREEDY_REALLOC(pcr_values, n_pcr_values + current_values->count))
c57d8bc8
DS
1078 return log_oom();
1079
c648a4b8 1080 memcpy_safe(&pcr_values[n_pcr_values], current_values->digests,
c57d8bc8 1081 current_values->count * sizeof(TPM2B_DIGEST));
c648a4b8 1082 n_pcr_values += current_values->count;
c57d8bc8
DS
1083
1084 if (DEBUG_LOGGING) {
1085 unsigned i = 0;
1086 FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, s, current_read) {
1087 assert(i < current_values->count);
1088
1089 TPM2B_DIGEST *d = &current_values->digests[i];
1090 i++;
1091
1092 TPML_PCR_SELECTION l;
1093 tpm2_tpml_pcr_selection_from_mask(INDEX_TO_MASK(uint32_t, pcr), s->hash, &l);
1094
1095 _cleanup_free_ char *desc = tpm2_tpml_pcr_selection_to_string(&l);
1096 tpm2_log_debug_digest(d, strna(desc));
1097 }
1098 }
321a9d9e
LP
1099 }
1100
c57d8bc8
DS
1101 if (ret_pcr_selection)
1102 *ret_pcr_selection = total_read;
1103 if (ret_pcr_values)
1104 *ret_pcr_values = TAKE_PTR(pcr_values);
c648a4b8
DS
1105 if (ret_n_pcr_values)
1106 *ret_n_pcr_values = n_pcr_values;
c57d8bc8
DS
1107
1108 return 0;
321a9d9e
LP
1109}
1110
1111static int tpm2_pcr_mask_good(
23e9ccc2 1112 Tpm2Context *c,
321a9d9e
LP
1113 TPMI_ALG_HASH bank,
1114 uint32_t mask) {
1115
c57d8bc8 1116 _cleanup_free_ TPM2B_DIGEST *pcr_values = NULL;
321a9d9e 1117 TPML_PCR_SELECTION selection;
c648a4b8 1118 size_t n_pcr_values = 0;
c57d8bc8 1119 int r;
321a9d9e
LP
1120
1121 assert(c);
1122
1123 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
1124 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
1125 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
1126
c69bd0ab 1127 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
321a9d9e 1128
c648a4b8 1129 r = tpm2_pcr_read(c, &selection, &selection, &pcr_values, &n_pcr_values);
c57d8bc8
DS
1130 if (r < 0)
1131 return r;
321a9d9e
LP
1132
1133 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
c57d8bc8
DS
1134 unsigned i = 0;
1135 FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, s, &selection) {
c648a4b8 1136 assert(i < n_pcr_values);
321a9d9e 1137
c57d8bc8
DS
1138 if (!memeqbyte(0x00, pcr_values[i].buffer, pcr_values[i].size) &&
1139 !memeqbyte(0xFF, pcr_values[i].buffer, pcr_values[i].size))
1140 return true;
321a9d9e 1141
c57d8bc8 1142 i++;
321a9d9e
LP
1143 }
1144
c57d8bc8 1145 return false;
321a9d9e
LP
1146}
1147
59fafaee
LP
1148static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
1149
1150 assert(selection);
1151
1152 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
1153 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
1154 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
1155 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
7bfe0a48 1156 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
1157 return false;
1158 }
1159
1160 assert_cc(TPM2_PCRS_MAX % 8 == 0);
1161
1162 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
1163 * enabled for this bank. Otherwise this TPM doesn't qualify. */
1164 bool valid = true;
1165 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
1166 if (selection->pcrSelect[j] != 0xFF) {
1167 valid = false;
1168 break;
1169 }
1170
1171 if (!valid)
1172 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
7bfe0a48 1173 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
1174
1175 return valid;
1176}
1177
07697bfe 1178static int tpm2_get_best_pcr_bank(
23e9ccc2 1179 Tpm2Context *c,
321a9d9e 1180 uint32_t pcr_mask,
07697bfe
LP
1181 TPMI_ALG_HASH *ret) {
1182
1183 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
321a9d9e 1184 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
07697bfe
LP
1185 TPMI_YES_NO more;
1186 TSS2_RC rc;
59fafaee 1187 int r;
07697bfe 1188
321a9d9e
LP
1189 assert(c);
1190
07697bfe 1191 rc = sym_Esys_GetCapability(
23e9ccc2 1192 c->esys_context,
07697bfe
LP
1193 ESYS_TR_NONE,
1194 ESYS_TR_NONE,
1195 ESYS_TR_NONE,
1196 TPM2_CAP_PCRS,
1197 0,
1198 1,
1199 &more,
1200 &pcap);
1201 if (rc != TSS2_RC_SUCCESS)
1202 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1203 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
1204
1205 assert(pcap->capability == TPM2_CAP_PCRS);
1206
1207 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
321a9d9e
LP
1208 int good;
1209
1210 /* For now we are only interested in the SHA1 and SHA256 banks */
1211 if (!IN_SET(pcap->data.assignedPCR.pcrSelections[i].hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
1212 continue;
07697bfe 1213
59fafaee
LP
1214 r = tpm2_bank_has24(pcap->data.assignedPCR.pcrSelections + i);
1215 if (r < 0)
1216 return r;
1217 if (!r)
07697bfe 1218 continue;
07697bfe 1219
321a9d9e
LP
1220 good = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
1221 if (good < 0)
1222 return good;
1223
07697bfe 1224 if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) {
321a9d9e
LP
1225 supported_hash = TPM2_ALG_SHA256;
1226 if (good) {
1227 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
1228 hash_with_valid_pcr = TPM2_ALG_SHA256;
1229 break;
1230 }
1231 } else {
1232 assert(pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1);
1233
1234 if (supported_hash == 0)
1235 supported_hash = TPM2_ALG_SHA1;
07697bfe 1236
321a9d9e
LP
1237 if (good && hash_with_valid_pcr == 0)
1238 hash_with_valid_pcr = TPM2_ALG_SHA1;
1239 }
07697bfe
LP
1240 }
1241
321a9d9e
LP
1242 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
1243 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
1244 * SHA1.
1245 *
1246 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
1247 * not initialized. */
1248
1249 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
1250 assert(supported_hash == TPM2_ALG_SHA256);
1251 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
1252 *ret = TPM2_ALG_SHA256;
1253 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
1254 if (supported_hash == TPM2_ALG_SHA256)
1255 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.");
1256 else {
1257 assert(supported_hash == TPM2_ALG_SHA1);
1258 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.");
1259 }
1260
1261 *ret = TPM2_ALG_SHA1;
1262 } else if (supported_hash == TPM2_ALG_SHA256) {
1263 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!");
1264 *ret = TPM2_ALG_SHA256;
1265 } else if (supported_hash == TPM2_ALG_SHA1) {
1266 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!");
1267 *ret = TPM2_ALG_SHA1;
1268 } else
07697bfe
LP
1269 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1270 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
1271
07697bfe
LP
1272 return 0;
1273}
1274
c5bf1f85 1275int tpm2_get_good_pcr_banks(
23e9ccc2 1276 Tpm2Context *c,
c5bf1f85
LP
1277 uint32_t pcr_mask,
1278 TPMI_ALG_HASH **ret) {
1279
1280 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
1281 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
1282 size_t n_good_banks = 0, n_fallback_banks = 0;
1283 TPMI_YES_NO more;
1284 TSS2_RC rc;
1285 int r;
1286
1287 assert(c);
1288 assert(ret);
1289
1290 rc = sym_Esys_GetCapability(
23e9ccc2 1291 c->esys_context,
c5bf1f85
LP
1292 ESYS_TR_NONE,
1293 ESYS_TR_NONE,
1294 ESYS_TR_NONE,
1295 TPM2_CAP_PCRS,
1296 0,
1297 1,
1298 &more,
1299 &pcap);
1300 if (rc != TSS2_RC_SUCCESS)
1301 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1302 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
1303
1304 assert(pcap->capability == TPM2_CAP_PCRS);
1305
1306 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
1307
1308 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
1309 r = tpm2_bank_has24(pcap->data.assignedPCR.pcrSelections + i);
1310 if (r < 0)
1311 return r;
1312 if (!r)
1313 continue;
1314
1315 /* Let's now see if this bank has any of the selected PCRs actually initialized */
1316 r = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
1317 if (r < 0)
1318 return r;
1319
1320 if (n_good_banks + n_fallback_banks >= INT_MAX)
1321 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
1322
1323 if (r) {
1324 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
1325 return log_oom();
1326
1327 good_banks[n_good_banks++] = pcap->data.assignedPCR.pcrSelections[i].hash;
1328 } else {
1329 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
1330 return log_oom();
1331
1332 fallback_banks[n_fallback_banks++] = pcap->data.assignedPCR.pcrSelections[i].hash;
1333 }
1334 }
1335
1336 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
1337 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
1338 if (n_good_banks > 0) {
1339 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
1340 *ret = TAKE_PTR(good_banks);
1341 return (int) n_good_banks;
1342 }
1343 if (n_fallback_banks > 0) {
1344 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
1345 *ret = TAKE_PTR(fallback_banks);
1346 return (int) n_fallback_banks;
1347 }
1348
1349 /* No suitable banks found. */
1350 *ret = NULL;
1351 return 0;
1352}
1353
e4481cc5 1354int tpm2_get_good_pcr_banks_strv(
23e9ccc2 1355 Tpm2Context *c,
e4481cc5
LP
1356 uint32_t pcr_mask,
1357 char ***ret) {
1358
0d7009d3 1359#if HAVE_OPENSSL
e4481cc5
LP
1360 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
1361 _cleanup_strv_free_ char **l = NULL;
1362 int n_algs;
1363
1364 assert(c);
1365 assert(ret);
1366
1367 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
1368 if (n_algs < 0)
1369 return n_algs;
1370
1371 for (int i = 0; i < n_algs; i++) {
1372 _cleanup_free_ char *n = NULL;
1373 const EVP_MD *implementation;
1374 const char *salg;
1375
7bfe0a48 1376 salg = tpm2_hash_alg_to_string(algs[i]);
e4481cc5
LP
1377 if (!salg)
1378 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
1379
1380 implementation = EVP_get_digestbyname(salg);
1381 if (!implementation)
1382 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
1383
1384 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
1385 if (!n)
1386 return log_oom();
1387
1388 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
1389
1390 if (strv_consume(&l, TAKE_PTR(n)) < 0)
1391 return log_oom();
1392 }
1393
1394 *ret = TAKE_PTR(l);
1395 return 0;
0d7009d3
DS
1396#else /* HAVE_OPENSSL */
1397 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
1398#endif
e4481cc5
LP
1399}
1400
da92d39a
DS
1401/* Hash data into the digest.
1402 *
1403 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
1404 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
1405 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
1406 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
1407 *
1408 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
1409 * correct for 'alg'.
1410 *
1411 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
1412int tpm2_digest_many(
1413 TPMI_ALG_HASH alg,
1414 TPM2B_DIGEST *digest,
1415 const struct iovec data[],
1416 size_t n_data,
1417 bool extend) {
1418
1419 struct sha256_ctx ctx;
1420
1421 assert(digest);
1422 assert(data || n_data == 0);
1423
1424 if (alg != TPM2_ALG_SHA256)
1425 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1426 "Hash algorithm not supported: 0x%x", alg);
1427
1428 if (extend && digest->size != SHA256_DIGEST_SIZE)
1429 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1430 "Digest size 0x%x, require 0x%x",
1431 digest->size, (unsigned)SHA256_DIGEST_SIZE);
1432
1433 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
1434 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
1435
1436 CLEANUP_ERASE(ctx);
1437
1438 sha256_init_ctx(&ctx);
1439
1440 if (extend)
1441 sha256_process_bytes(digest->buffer, digest->size, &ctx);
1442 else {
1443 *digest = (TPM2B_DIGEST){ .size = SHA256_DIGEST_SIZE, };
1444 if (n_data == 0) /* If not extending and no data, return zero hash */
1445 return 0;
1446 }
1447
1448 for (size_t i = 0; i < n_data; i++)
1449 sha256_process_bytes(data[i].iov_base, data[i].iov_len, &ctx);
1450
1451 sha256_finish_ctx(&ctx, digest->buffer);
1452
1453 return 0;
1454}
1455
1456/* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
1457int tpm2_digest_many_digests(
1458 TPMI_ALG_HASH alg,
1459 TPM2B_DIGEST *digest,
1460 const TPM2B_DIGEST data[],
1461 size_t n_data,
1462 bool extend) {
1463
1464 _cleanup_free_ struct iovec *iovecs = NULL;
1465
1466 assert(data || n_data == 0);
1467
1468 iovecs = new(struct iovec, n_data);
1469 if (!iovecs)
1470 return log_oom();
1471
1472 for (size_t i = 0; i < n_data; i++)
1473 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
1474
1475 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
1476}
1477
409a65f8
DS
1478static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
1479 TPM2B_AUTH auth = {};
1480 TSS2_RC rc;
1481 int r;
1482
1483 assert(c);
1484 assert(handle);
1485
1486 if (!pin)
1487 return 0;
1488
1489 CLEANUP_ERASE(auth);
1490
1491 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &auth, pin, strlen(pin), /* extend= */ false);
1492 if (r < 0)
1493 return r;
1494
1495 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, &auth);
1496 if (rc != TSS2_RC_SUCCESS)
1497 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1498 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
1499
1500 return 0;
1501}
1502
e976445d
DS
1503static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
1504 TPMA_SESSION flags = 0;
1505 TSS2_RC rc;
1506
1507 assert(c);
1508 assert(session);
1509
1510 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
1511 if (rc != TSS2_RC_SUCCESS)
1512 return false;
1513
1514 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
1515}
1516
da29de23 1517static int tpm2_make_encryption_session(
23e9ccc2 1518 Tpm2Context *c,
16e16b8c
DS
1519 const Tpm2Handle *primary,
1520 const Tpm2Handle *bind_key,
16e16b8c 1521 Tpm2Handle **ret_session) {
da29de23
GG
1522
1523 static const TPMT_SYM_DEF symmetric = {
1524 .algorithm = TPM2_ALG_AES,
4dde902e
LP
1525 .keyBits.aes = 128,
1526 .mode.aes = TPM2_ALG_CFB,
da29de23
GG
1527 };
1528 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
1529 TPMA_SESSION_CONTINUESESSION;
da29de23 1530 TSS2_RC rc;
16e16b8c 1531 int r;
da29de23
GG
1532
1533 assert(c);
16e16b8c 1534 assert(ret_session);
da29de23
GG
1535
1536 log_debug("Starting HMAC encryption session.");
1537
1538 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
1539 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
1540 * recover the salt, which is then used for key derivation. */
16e16b8c
DS
1541 _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
1542 r = tpm2_handle_new(c, &session);
1543 if (r < 0)
1544 return r;
1545
da29de23 1546 rc = sym_Esys_StartAuthSession(
23e9ccc2 1547 c->esys_context,
16e16b8c
DS
1548 primary->esys_handle,
1549 bind_key->esys_handle,
da29de23
GG
1550 ESYS_TR_NONE,
1551 ESYS_TR_NONE,
1552 ESYS_TR_NONE,
1553 NULL,
1554 TPM2_SE_HMAC,
1555 &symmetric,
1556 TPM2_ALG_SHA256,
16e16b8c 1557 &session->esys_handle);
da29de23
GG
1558 if (rc != TSS2_RC_SUCCESS)
1559 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1560 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
1561
1562 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
1563 * always used for sessions), this provides confidentiality, integrity and replay protection for
1564 * operations that use this session. */
16e16b8c 1565 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
da29de23
GG
1566 if (rc != TSS2_RC_SUCCESS)
1567 return log_error_errno(
1568 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1569 "Failed to configure TPM session: %s",
1570 sym_Tss2_RC_Decode(rc));
1571
16e16b8c 1572 *ret_session = TAKE_PTR(session);
da29de23 1573
da29de23
GG
1574 return 0;
1575}
1576
2cd9d575
DS
1577static int tpm2_make_policy_session(
1578 Tpm2Context *c,
1579 const Tpm2Handle *primary,
1580 const Tpm2Handle *encryption_session,
1581 bool trial,
1582 Tpm2Handle **ret_session) {
1583
1584 static const TPMT_SYM_DEF symmetric = {
1585 .algorithm = TPM2_ALG_AES,
1586 .keyBits.aes = 128,
1587 .mode.aes = TPM2_ALG_CFB,
1588 };
1589 TPM2_SE session_type = trial ? TPM2_SE_TRIAL : TPM2_SE_POLICY;
1590 TSS2_RC rc;
1591 int r;
1592
1593 assert(c);
1594 assert(primary);
1595 assert(encryption_session);
1596 assert(ret_session);
1597
1598 if (!tpm2_is_encryption_session(c, encryption_session))
1599 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1600 "Missing encryption session");
1601
1602 log_debug("Starting policy session.");
1603
1604 _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
1605 r = tpm2_handle_new(c, &session);
1606 if (r < 0)
1607 return r;
1608
1609 rc = sym_Esys_StartAuthSession(
1610 c->esys_context,
1611 primary->esys_handle,
1612 ESYS_TR_NONE,
1613 encryption_session->esys_handle,
1614 ESYS_TR_NONE,
1615 ESYS_TR_NONE,
1616 NULL,
1617 session_type,
1618 &symmetric,
1619 TPM2_ALG_SHA256,
1620 &session->esys_handle);
1621 if (rc != TSS2_RC_SUCCESS)
1622 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1623 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
1624
1625 *ret_session = TAKE_PTR(session);
1626
1627 return 0;
1628}
1629
95898241
DS
1630static int openssl_pubkey_to_tpm2_pubkey(
1631 const void *pubkey,
1632 size_t pubkey_size,
1633 TPM2B_PUBLIC *output,
1634 void **ret_fp,
1635 size_t *ret_fp_size) {
1636
395c1d9a 1637#if HAVE_OPENSSL
d9b5841d
LP
1638#if OPENSSL_VERSION_MAJOR >= 3
1639 _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL;
1640#else
1641 const BIGNUM *n = NULL, *e = NULL;
1642 const RSA *rsa = NULL;
1643#endif
95898241 1644 int r, n_bytes, e_bytes;
d9b5841d 1645
95898241
DS
1646 assert(pubkey);
1647 assert(pubkey_size > 0);
d9b5841d
LP
1648 assert(output);
1649
1650 /* Converts an OpenSSL public key to a structure that the TPM chip can process. */
1651
95898241
DS
1652 _cleanup_fclose_ FILE *f = NULL;
1653 f = fmemopen((void*) pubkey, pubkey_size, "r");
1654 if (!f)
1655 return log_oom();
1656
1657 _cleanup_(EVP_PKEY_freep) EVP_PKEY *input = NULL;
1658 input = PEM_read_PUBKEY(f, NULL, NULL, NULL);
1659 if (!input)
1660 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
1661
d9b5841d
LP
1662 if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA)
1663 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key.");
1664
1665#if OPENSSL_VERSION_MAJOR >= 3
1666 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_N, &n))
1667 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
1668#else
1669 rsa = EVP_PKEY_get0_RSA(input);
1670 if (!rsa)
1671 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to extract RSA key from public key.");
1672
1673 n = RSA_get0_n(rsa);
1674 if (!n)
1675 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
1676#endif
1677
1678 n_bytes = BN_num_bytes(n);
1679 assert_se(n_bytes > 0);
1680 if ((size_t) n_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.unique.rsa.buffer))
1681 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA modulus too large for TPM2 public key object.");
1682
1683#if OPENSSL_VERSION_MAJOR >= 3
1684 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_E, &e))
1685 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
1686#else
1687 e = RSA_get0_e(rsa);
1688 if (!e)
1689 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
1690#endif
1691
1692 e_bytes = BN_num_bytes(e);
1693 assert_se(e_bytes > 0);
1694 if ((size_t) e_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.parameters.rsaDetail.exponent))
1695 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA exponent too large for TPM2 public key object.");
1696
1697 *output = (TPM2B_PUBLIC) {
1698 .size = sizeof(TPMT_PUBLIC),
1699 .publicArea = {
1700 .type = TPM2_ALG_RSA,
1701 .nameAlg = TPM2_ALG_SHA256,
1702 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
1703 .parameters.rsaDetail = {
1704 .scheme = {
1705 .scheme = TPM2_ALG_NULL,
1706 .details.anySig.hashAlg = TPM2_ALG_NULL,
1707 },
1708 .symmetric = {
1709 .algorithm = TPM2_ALG_NULL,
1710 .mode.sym = TPM2_ALG_NULL,
1711 },
1712 .keyBits = n_bytes * 8,
1713 /* .exponent will be filled in below. */
1714 },
1715 .unique = {
1716 .rsa.size = n_bytes,
1717 /* .rsa.buffer will be filled in below. */
1718 },
1719 },
1720 };
1721
1722 if (BN_bn2bin(n, output->publicArea.unique.rsa.buffer) <= 0)
1723 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA modulus.");
1724
1725 if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0)
1726 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent.");
1727
95898241
DS
1728 if (ret_fp) {
1729 _cleanup_free_ void *fp = NULL;
1730 size_t fp_size;
1731
1732 assert(ret_fp_size);
1733
1734 r = pubkey_fingerprint(input, EVP_sha256(), &fp, &fp_size);
1735 if (r < 0)
1736 return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
1737
1738 *ret_fp = TAKE_PTR(fp);
1739 *ret_fp_size = fp_size;
1740 }
1741
d9b5841d 1742 return 0;
95898241
DS
1743#else /* HAVE_OPENSSL */
1744 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
1745#endif
d9b5841d
LP
1746}
1747
1748static int find_signature(
1749 JsonVariant *v,
95898241
DS
1750 const TPML_PCR_SELECTION *pcr_selection,
1751 const void *fp,
1752 size_t fp_size,
d9b5841d
LP
1753 const void *policy,
1754 size_t policy_size,
1755 void *ret_signature,
1756 size_t *ret_signature_size) {
1757
95898241 1758#if HAVE_OPENSSL
d9b5841d 1759 JsonVariant *b, *i;
d9b5841d
LP
1760 const char *k;
1761 int r;
1762
1763 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
1764 * public key, and policy digest. */
1765
1766 if (!json_variant_is_object(v))
1767 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
1768
95898241
DS
1769 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
1770 uint32_t pcr_mask;
1771 r = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank, &pcr_mask);
1772 if (r < 0)
1773 return r;
1774
7bfe0a48 1775 k = tpm2_hash_alg_to_string(pcr_bank);
d9b5841d
LP
1776 if (!k)
1777 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
1778
1779 /* First, find field by bank */
1780 b = json_variant_by_key(v, k);
1781 if (!b)
1782 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
1783
1784 if (!json_variant_is_array(b))
1785 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
1786
1787 /* Now iterate through all signatures known for this bank */
1788 JSON_VARIANT_ARRAY_FOREACH(i, b) {
1789 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
1790 JsonVariant *maskj, *fpj, *sigj, *polj;
1791 size_t fpj_size, polj_size;
1792 uint32_t parsed_mask;
1793
1794 if (!json_variant_is_object(i))
1795 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
1796
1797 /* Check if the PCR mask matches our expectations */
1798 maskj = json_variant_by_key(i, "pcrs");
1799 if (!maskj)
1800 continue;
1801
1802 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
1803 if (r < 0)
1804 return log_error_errno(r, "Failed to parse JSON PCR mask");
1805
1806 if (parsed_mask != pcr_mask)
1807 continue; /* Not for this PCR mask */
1808
1809 /* Then check if this is for the public key we operate with */
1810 fpj = json_variant_by_key(i, "pkfp");
1811 if (!fpj)
1812 continue;
1813
1814 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
1815 if (r < 0)
1816 return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
1817
d9b5841d
LP
1818 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
1819 continue; /* Not for this public key */
1820
1821 /* Finally, check if this is for the PCR policy we expect this to be */
1822 polj = json_variant_by_key(i, "pol");
1823 if (!polj)
1824 continue;
1825
1826 r = json_variant_unhex(polj, &polj_data, &polj_size);
1827 if (r < 0)
1828 return log_error_errno(r, "Failed to decode policy hash JSON data: %m");
1829
1830 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
1831 continue;
1832
1833 /* This entry matches all our expectations, now return the signature included in it */
1834 sigj = json_variant_by_key(i, "sig");
1835 if (!sigj)
1836 continue;
1837
1838 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
1839 }
1840
1841 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
95898241
DS
1842#else /* HAVE_OPENSSL */
1843 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
395c1d9a 1844#endif
95898241 1845}
d9b5841d 1846
dbae4b95
DS
1847/* Calculates the "name" of a public key.
1848 *
1849 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
1850 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
1851 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
1852 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
1853 * that would also change the key name.
1854 *
1855 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
1856 * nameAlg is not TPM2_ALG_SHA256. */
1857int tpm2_calculate_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
1858 TSS2_RC rc;
1859 int r;
1860
1861 assert(public);
1862 assert(ret_name);
1863
1864 r = dlopen_tpm2();
1865 if (r < 0)
1866 return log_error_errno(r, "TPM2 support not installed: %m");
1867
1868 if (public->nameAlg != TPM2_ALG_SHA256)
1869 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1870 "Unsupported nameAlg: 0x%x",
1871 public->nameAlg);
1872
1873 _cleanup_free_ uint8_t *buf = NULL;
1874 size_t size = 0;
1875
1876 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
1877 if (!buf)
1878 return log_oom();
1879
1880 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
1881 if (rc != TSS2_RC_SUCCESS)
1882 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1883 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
1884
1885 TPM2B_DIGEST digest = {};
1886 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
1887 if (r < 0)
1888 return r;
1889
1890 TPMT_HA ha = {
1891 .hashAlg = TPM2_ALG_SHA256,
1892 };
1893 assert(digest.size <= sizeof(ha.digest.sha256));
1894 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
1895
1896 TPM2B_NAME name;
1897 size = 0;
1898 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
1899 if (rc != TSS2_RC_SUCCESS)
1900 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1901 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
1902 name.size = size;
1903
1904 tpm2_log_debug_name(&name, "Calculated name");
1905
1906 *ret_name = name;
1907
1908 return 0;
1909}
1910
1911/* Get the "name" of a key from the TPM.
1912 *
1913 * The "name" of a key is explained above in tpm2_calculate_name().
1914 *
1915 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
1916 * public/private keypair. */
1917static int tpm2_get_name(
1918 Tpm2Context *c,
1919 const Tpm2Handle *handle,
1920 TPM2B_NAME **ret_name) {
1921
1922 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
1923 TSS2_RC rc;
1924
1925 assert(c);
1926 assert(handle);
1927 assert(ret_name);
1928
1929 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
1930 if (rc != TSS2_RC_SUCCESS)
1931 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1932 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
1933
1934 tpm2_log_debug_name(name, "Object name");
1935
1936 *ret_name = TAKE_PTR(name);
1937
1938 return 0;
1939}
1940
8a716354
DS
1941/* Extend 'digest' with the PolicyAuthValue calculated hash. */
1942int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
1943 TPM2_CC command = TPM2_CC_PolicyAuthValue;
1944 TSS2_RC rc;
1945 int r;
1946
1947 assert(digest);
1948 assert(digest->size == SHA256_DIGEST_SIZE);
1949
1950 r = dlopen_tpm2();
1951 if (r < 0)
1952 return log_error_errno(r, "TPM2 support not installed: %m");
1953
1954 uint8_t buf[sizeof(command)];
1955 size_t offset = 0;
1956
1957 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
1958 if (rc != TSS2_RC_SUCCESS)
1959 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1960 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
1961
1962 if (offset != sizeof(command))
1963 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1964 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
1965
1966 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
1967 if (r < 0)
1968 return r;
1969
1970 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
1971
1972 return 0;
1973}
1974
1975static int tpm2_policy_auth_value(
1976 Tpm2Context *c,
1977 const Tpm2Handle *session,
1978 TPM2B_DIGEST **ret_policy_digest) {
1979
1980 TSS2_RC rc;
1981
1982 assert(c);
1983 assert(session);
1984
1985 log_debug("Adding authValue policy.");
1986
1987 rc = sym_Esys_PolicyAuthValue(
1988 c->esys_context,
1989 session->esys_handle,
1990 ESYS_TR_NONE,
1991 ESYS_TR_NONE,
1992 ESYS_TR_NONE);
1993 if (rc != TSS2_RC_SUCCESS)
1994 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1995 "Failed to add authValue policy to TPM: %s",
1996 sym_Tss2_RC_Decode(rc));
1997
1998 return tpm2_get_policy_digest(c, session, ret_policy_digest);
1999}
2000
dcbc4674
DS
2001/* Extend 'digest' with the PolicyPCR calculated hash. */
2002int tpm2_calculate_policy_pcr(
2003 const TPML_PCR_SELECTION *pcr_selection,
2004 const TPM2B_DIGEST pcr_values[],
2005 size_t n_pcr_values,
2006 TPM2B_DIGEST *digest) {
2007
2008 TPM2_CC command = TPM2_CC_PolicyPCR;
2009 TSS2_RC rc;
2010 int r;
2011
2012 assert(pcr_selection);
2013 assert(pcr_values || n_pcr_values == 0);
2014 assert(digest);
2015 assert(digest->size == SHA256_DIGEST_SIZE);
2016
2017 r = dlopen_tpm2();
2018 if (r < 0)
2019 return log_error_errno(r, "TPM2 support not installed: %m");
2020
2021 TPM2B_DIGEST hash = {};
2022 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, pcr_values, n_pcr_values, /* extend= */ false);
2023 if (r < 0)
2024 return r;
2025
2026 _cleanup_free_ uint8_t *buf = NULL;
2027 size_t size = 0, maxsize = sizeof(command) + sizeof(*pcr_selection);
2028
2029 buf = malloc(maxsize);
2030 if (!buf)
2031 return log_oom();
2032
2033 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
2034 if (rc != TSS2_RC_SUCCESS)
2035 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2036 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
2037
2038 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(pcr_selection, buf, maxsize, &size);
2039 if (rc != TSS2_RC_SUCCESS)
2040 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2041 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
2042
2043 struct iovec data[] = {
2044 IOVEC_MAKE(buf, size),
2045 IOVEC_MAKE(hash.buffer, hash.size),
2046 };
2047 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
2048 if (r < 0)
2049 return r;
2050
2051 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
2052
2053 return 0;
2054}
2055
2056static int tpm2_policy_pcr(
2057 Tpm2Context *c,
2058 const Tpm2Handle *session,
2059 const TPML_PCR_SELECTION *pcr_selection,
2060 TPM2B_DIGEST **ret_policy_digest) {
2061
2062 TSS2_RC rc;
2063
2064 assert(c);
2065 assert(session);
2066 assert(pcr_selection);
2067
2068 log_debug("Adding PCR hash policy.");
2069
2070 rc = sym_Esys_PolicyPCR(
2071 c->esys_context,
2072 session->esys_handle,
2073 ESYS_TR_NONE,
2074 ESYS_TR_NONE,
2075 ESYS_TR_NONE,
2076 NULL,
2077 pcr_selection);
2078 if (rc != TSS2_RC_SUCCESS)
2079 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2080 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
2081
2082 return tpm2_get_policy_digest(c, session, ret_policy_digest);
2083}
2084
5c7852f7
DS
2085/* Extend 'digest' with the PolicyAuthorize calculated hash. */
2086int tpm2_calculate_policy_authorize(
2087 const TPM2B_PUBLIC *public,
2088 const TPM2B_DIGEST *policy_ref,
2089 TPM2B_DIGEST *digest) {
2090
2091 TPM2_CC command = TPM2_CC_PolicyAuthorize;
2092 TSS2_RC rc;
2093 int r;
2094
2095 assert(public);
2096 assert(digest);
2097 assert(digest->size == SHA256_DIGEST_SIZE);
2098
2099 r = dlopen_tpm2();
2100 if (r < 0)
2101 return log_error_errno(r, "TPM2 support not installed: %m");
2102
2103 uint8_t buf[sizeof(command)];
2104 size_t offset = 0;
2105
2106 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
2107 if (rc != TSS2_RC_SUCCESS)
2108 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2109 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
2110
2111 if (offset != sizeof(command))
2112 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2113 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
2114
2115 TPM2B_NAME name = {};
2116 r = tpm2_calculate_name(&public->publicArea, &name);
2117 if (r < 0)
2118 return r;
2119
2120 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
2121 zero(digest->buffer);
2122
2123 struct iovec data[] = {
2124 IOVEC_MAKE(buf, offset),
2125 IOVEC_MAKE(name.name, name.size),
2126 };
2127 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
2128 if (r < 0)
2129 return r;
2130
2131 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
2132 if (policy_ref)
2133 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
2134 else
2135 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
2136 if (r < 0)
2137 return r;
2138
2139 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
2140
2141 return 0;
2142}
2143
2144static int tpm2_policy_authorize(
2145 Tpm2Context *c,
2146 const Tpm2Handle *session,
2147 TPML_PCR_SELECTION *pcr_selection,
2148 const TPM2B_PUBLIC *public,
2149 const void *fp,
2150 size_t fp_size,
2151 JsonVariant *signature_json,
2152 TPM2B_DIGEST **ret_policy_digest) {
2153
2154 TSS2_RC rc;
2155 int r;
2156
2157 assert(c);
2158 assert(session);
2159 assert(pcr_selection);
2160 assert(public);
2161 assert(fp && fp_size > 0);
2162
2163 log_debug("Adding PCR signature policy.");
2164
2165 _cleanup_tpm2_handle_ Tpm2Handle *pubkey_handle = NULL;
2166 r = tpm2_handle_new(c, &pubkey_handle);
2167 if (r < 0)
2168 return r;
2169
2170 /* Load the key into the TPM */
2171 rc = sym_Esys_LoadExternal(
2172 c->esys_context,
2173 ESYS_TR_NONE,
2174 ESYS_TR_NONE,
2175 ESYS_TR_NONE,
2176 NULL,
2177 public,
2178#if HAVE_TSS2_ESYS3
2179 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2180 * hierarchy, older versions need TPM2_RH_* instead. */
2181 ESYS_TR_RH_OWNER,
2182#else
2183 TPM2_RH_OWNER,
2184#endif
2185 &pubkey_handle->esys_handle);
2186 if (rc != TSS2_RC_SUCCESS)
2187 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2188 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
2189
2190 /* Acquire the "name" of what we just loaded */
2191 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
2192 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
2193 if (r < 0)
2194 return r;
2195
2196 /* If we have a signature, proceed with verifying the PCR digest */
2197 const TPMT_TK_VERIFIED *check_ticket;
2198 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
2199 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
2200 if (signature_json) {
2201 r = tpm2_policy_pcr(
2202 c,
2203 session,
2204 pcr_selection,
2205 &approved_policy);
2206 if (r < 0)
2207 return r;
2208
2209 _cleanup_free_ void *signature_raw = NULL;
2210 size_t signature_size;
2211
2212 r = find_signature(
2213 signature_json,
2214 pcr_selection,
2215 fp, fp_size,
2216 approved_policy->buffer,
2217 approved_policy->size,
2218 &signature_raw,
2219 &signature_size);
2220 if (r < 0)
2221 return r;
2222
2223 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
2224 * hence we need to do the SHA256 part ourselves, first */
2225 TPM2B_DIGEST signature_hash = *approved_policy;
2226 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
2227 if (r < 0)
2228 return r;
2229
2230 TPMT_SIGNATURE policy_signature = {
2231 .sigAlg = TPM2_ALG_RSASSA,
2232 .signature.rsassa = {
2233 .hash = TPM2_ALG_SHA256,
2234 .sig.size = signature_size,
2235 },
2236 };
2237 if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer))
2238 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
2239 memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
2240
2241 rc = sym_Esys_VerifySignature(
2242 c->esys_context,
2243 pubkey_handle->esys_handle,
2244 ESYS_TR_NONE,
2245 ESYS_TR_NONE,
2246 ESYS_TR_NONE,
2247 &signature_hash,
2248 &policy_signature,
2249 &check_ticket_buffer);
2250 if (rc != TSS2_RC_SUCCESS)
2251 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2252 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
2253
2254 check_ticket = check_ticket_buffer;
2255 } else {
2256 /* When enrolling, we pass a NULL ticket */
2257 static const TPMT_TK_VERIFIED check_ticket_null = {
2258 .tag = TPM2_ST_VERIFIED,
2259 .hierarchy = TPM2_RH_OWNER,
2260 };
2261
2262 check_ticket = &check_ticket_null;
2263 }
2264
2265 rc = sym_Esys_PolicyAuthorize(
2266 c->esys_context,
2267 session->esys_handle,
2268 ESYS_TR_NONE,
2269 ESYS_TR_NONE,
2270 ESYS_TR_NONE,
2271 approved_policy,
2272 /* policyRef= */ &(const TPM2B_NONCE) {},
2273 pubkey_name,
2274 check_ticket);
2275 if (rc != TSS2_RC_SUCCESS)
2276 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2277 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
2278
2279 return tpm2_get_policy_digest(c, session, ret_policy_digest);
2280}
2281
d9a1f1a7
DS
2282/* Extend 'digest' with the calculated policy hash. */
2283static int tpm2_calculate_sealing_policy(
2284 const TPML_PCR_SELECTION *hash_pcr_selection,
2285 const TPM2B_DIGEST *hash_pcr_values,
2286 size_t n_hash_pcr_values,
2287 const TPM2B_PUBLIC *public,
2288 const char *pin,
2289 TPM2B_DIGEST *digest) {
2290
2291 int r;
2292
2293 assert(digest);
2294
2295 if (public) {
2296 r = tpm2_calculate_policy_authorize(public, NULL, digest);
2297 if (r < 0)
2298 return r;
2299 }
2300
2301 if (hash_pcr_selection && !tpm2_tpml_pcr_selection_is_empty(hash_pcr_selection)) {
2302 r = tpm2_calculate_policy_pcr(hash_pcr_selection, hash_pcr_values, n_hash_pcr_values, digest);
2303 if (r < 0)
2304 return r;
2305 }
2306
2307 if (pin) {
2308 r = tpm2_calculate_policy_auth_value(digest);
2309 if (r < 0)
2310 return r;
2311 }
2312
2313 return 0;
2314}
2315
2cd9d575 2316static int tpm2_build_sealing_policy(
23e9ccc2 2317 Tpm2Context *c,
2cd9d575 2318 const Tpm2Handle *session,
d9b5841d 2319 uint32_t hash_pcr_mask,
2cd9d575 2320 uint16_t pcr_bank,
524cef3f
DS
2321 const TPM2B_PUBLIC *public,
2322 const void *fp,
2323 size_t fp_size,
d9b5841d
LP
2324 uint32_t pubkey_pcr_mask,
2325 JsonVariant *signature_json,
2f5a892a 2326 bool use_pin,
2cd9d575 2327 TPM2B_DIGEST **ret_policy_digest) {
5e521624 2328
5e521624
LP
2329 int r;
2330
2331 assert(c);
2cd9d575 2332 assert(session);
524cef3f 2333 assert(pubkey_pcr_mask == 0 || public);
5e521624 2334
2cd9d575 2335 log_debug("Building sealing policy.");
251d2ea2 2336
d9b5841d 2337 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
2cd9d575
DS
2338 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
2339 if (r < 0)
2340 return r;
2341 if (r == 0)
2342 log_warning("Selected TPM2 PCRs are not initialized on this system.");
d9b5841d 2343 }
321a9d9e 2344
d9b5841d 2345 if (pubkey_pcr_mask != 0) {
d9b5841d 2346 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 2347 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
524cef3f 2348 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
23b972d5
DS
2349 if (r < 0)
2350 return r;
d9b5841d
LP
2351 }
2352
2353 if (hash_pcr_mask != 0) {
d9b5841d 2354 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 2355 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
dcbc4674
DS
2356 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
2357 if (r < 0)
2358 return r;
5e521624
LP
2359 }
2360
2f5a892a 2361 if (use_pin) {
8a716354
DS
2362 r = tpm2_policy_auth_value(c, session, NULL);
2363 if (r < 0)
2364 return r;
2f5a892a
GG
2365 }
2366
23b972d5
DS
2367 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
2368 if (r < 0)
2369 return r;
5e521624 2370
16e16b8c 2371 return 0;
5e521624
LP
2372}
2373
d9b5841d
LP
2374int tpm2_seal(const char *device,
2375 uint32_t hash_pcr_mask,
2376 const void *pubkey,
2377 const size_t pubkey_size,
2378 uint32_t pubkey_pcr_mask,
2379 const char *pin,
2380 void **ret_secret,
2381 size_t *ret_secret_size,
2382 void **ret_blob,
2383 size_t *ret_blob_size,
2384 void **ret_pcr_hash,
2385 size_t *ret_pcr_hash_size,
2386 uint16_t *ret_pcr_bank,
acbb504e
WR
2387 uint16_t *ret_primary_alg,
2388 void **ret_srk_buf,
2389 size_t *ret_srk_buf_size) {
5e521624 2390
5e521624
LP
2391 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2392 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
acbb504e 2393 _cleanup_(Esys_Freep) uint8_t *srk_buf = NULL;
5e521624
LP
2394 static const TPML_PCR_SELECTION creation_pcr = {};
2395 _cleanup_(erase_and_freep) void *secret = NULL;
e8858f11 2396 _cleanup_free_ void *hash = NULL;
692597c8 2397 TPM2B_SENSITIVE_CREATE hmac_sensitive;
5e521624 2398 TPM2B_PUBLIC hmac_template;
5e521624
LP
2399 usec_t start;
2400 TSS2_RC rc;
acbb504e 2401 size_t srk_buf_size;
5e521624
LP
2402 int r;
2403
d9b5841d
LP
2404 assert(pubkey || pubkey_size == 0);
2405
5e521624
LP
2406 assert(ret_secret);
2407 assert(ret_secret_size);
2408 assert(ret_blob);
2409 assert(ret_blob_size);
2410 assert(ret_pcr_hash);
2411 assert(ret_pcr_hash_size);
07697bfe 2412 assert(ret_pcr_bank);
5e521624 2413
d9b5841d
LP
2414 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
2415 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624
LP
2416
2417 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
2418 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
2b92a672
LP
2419 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
2420 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
2421 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
2422 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
2423 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
2424 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
2425 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
2426 * LUKS2 JSON header.
5e521624
LP
2427 *
2428 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
2429 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
2430 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
2431 * binding the unlocking to the TPM2 chip. */
2432
2433 start = now(CLOCK_MONOTONIC);
2434
692597c8
LP
2435 CLEANUP_ERASE(hmac_sensitive);
2436
68d084ce
DS
2437 _cleanup_tpm2_context_ Tpm2Context *c = NULL;
2438 r = tpm2_context_new(device, &c);
5e521624
LP
2439 if (r < 0)
2440 return r;
2441
2cd9d575
DS
2442 TPMI_ALG_HASH pcr_bank = 0;
2443 if (hash_pcr_mask | pubkey_pcr_mask) {
2444 /* Some TPM2 devices only can do SHA1. Prefer SHA256 but allow SHA1. */
2445 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
2446 if (r < 0)
2447 return r;
2448 }
2449
d9a1f1a7
DS
2450 TPML_PCR_SELECTION hash_pcr_selection = {};
2451 _cleanup_free_ TPM2B_DIGEST *hash_pcr_values = NULL;
2452 size_t n_hash_pcr_values = 0;
2453 if (hash_pcr_mask) {
2454 /* For now, we just read the current values from the system; we need to be able to specify
2455 * expected values, eventually. */
2456 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, pcr_bank, &hash_pcr_selection);
2457 r = tpm2_pcr_read(c, &hash_pcr_selection, &hash_pcr_selection, &hash_pcr_values, &n_hash_pcr_values);
2458 if (r < 0)
2459 return r;
2460 }
2461
524cef3f 2462 TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
524cef3f 2463 if (pubkey) {
d9a1f1a7 2464 r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, NULL, NULL);
524cef3f
DS
2465 if (r < 0)
2466 return r;
2467 authorize_key = &pubkey_tpm2;
2468 }
2469
d9a1f1a7
DS
2470 TPM2B_DIGEST policy_digest;
2471 r = tpm2_digest_init(TPM2_ALG_SHA256, &policy_digest);
2cd9d575
DS
2472 if (r < 0)
2473 return r;
2474
d9a1f1a7
DS
2475 r = tpm2_calculate_sealing_policy(
2476 &hash_pcr_selection,
2477 hash_pcr_values,
2478 n_hash_pcr_values,
524cef3f 2479 authorize_key,
d9a1f1a7 2480 pin,
2cd9d575 2481 &policy_digest);
5e521624 2482 if (r < 0)
16e16b8c 2483 return r;
5e521624
LP
2484
2485 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
2486 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
2487 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
2488 hmac_template = (TPM2B_PUBLIC) {
2489 .size = sizeof(TPMT_PUBLIC),
2490 .publicArea = {
2491 .type = TPM2_ALG_KEYEDHASH,
2492 .nameAlg = TPM2_ALG_SHA256,
2493 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
821d94c4 2494 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
1200777b 2495 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
d9a1f1a7 2496 .authPolicy = policy_digest,
5e521624
LP
2497 },
2498 };
2499
2500 hmac_sensitive = (TPM2B_SENSITIVE_CREATE) {
2501 .size = sizeof(hmac_sensitive.sensitive),
2502 .sensitive.data.size = 32,
2503 };
94a4ff2d
DS
2504 if (pin) {
2505 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &hmac_sensitive.sensitive.userAuth, pin, strlen(pin), /* extend= */ false);
2506 if (r < 0)
2507 return r;
2508 }
0e15c14f 2509
5e521624
LP
2510 assert(sizeof(hmac_sensitive.sensitive.data.buffer) >= hmac_sensitive.sensitive.data.size);
2511
23e9ccc2 2512 (void) tpm2_credit_random(c);
5e521624
LP
2513
2514 log_debug("Generating secret key data.");
2515
87cb1ab6 2516 r = crypto_random_bytes(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
16e16b8c
DS
2517 if (r < 0)
2518 return log_error_errno(r, "Failed to generate secret key: %m");
5e521624 2519
d9a1f1a7
DS
2520 _cleanup_tpm2_handle_ Tpm2Handle *primary_handle = NULL;
2521 TPMI_ALG_PUBLIC primary_alg;
2522 r = tpm2_make_primary(c, /* alg = */0, !!ret_srk_buf, &primary_alg, &primary_handle);
2523 if (r < 0)
2524 return r;
2525
2526 _cleanup_tpm2_handle_ Tpm2Handle *encryption_session = NULL;
2527 r = tpm2_make_encryption_session(c, primary_handle, &TPM2_HANDLE_NONE, &encryption_session);
2528 if (r < 0)
2529 return r;
2530
5e521624
LP
2531 log_debug("Creating HMAC key.");
2532
2533 rc = sym_Esys_Create(
68d084ce 2534 c->esys_context,
d9a1f1a7 2535 primary_handle->esys_handle,
2cd9d575 2536 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
5e521624
LP
2537 ESYS_TR_NONE,
2538 ESYS_TR_NONE,
2539 &hmac_sensitive,
2540 &hmac_template,
2541 NULL,
2542 &creation_pcr,
2543 &private,
2544 &public,
2545 NULL,
2546 NULL,
2547 NULL);
16e16b8c
DS
2548 if (rc != TSS2_RC_SUCCESS)
2549 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2550 "Failed to generate HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
5e521624
LP
2551
2552 secret = memdup(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
16e16b8c
DS
2553 if (!secret)
2554 return log_oom();
5e521624
LP
2555
2556 log_debug("Marshalling private and public part of HMAC key.");
2557
e8858f11
DS
2558 _cleanup_free_ void *blob = NULL;
2559 size_t max_size = sizeof(*private) + sizeof(*public), blob_size = 0;
5e521624 2560
e8858f11
DS
2561 blob = malloc0(max_size);
2562 if (!blob)
2563 return log_oom();
5e521624 2564
e8858f11
DS
2565 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
2566 if (rc != TSS2_RC_SUCCESS)
2567 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2568 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
5e521624 2569
e8858f11
DS
2570 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
2571 if (rc != TSS2_RC_SUCCESS)
2572 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2573 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
5e521624 2574
d9a1f1a7 2575 hash = memdup(policy_digest.buffer, policy_digest.size);
5e521624
LP
2576 if (!hash)
2577 return log_oom();
2578
acbb504e
WR
2579 /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
2580 * the raw TPM handle as well as the object name. The object name is used to verify that
2581 * the key we use later is the key we expect to establish the session with.
2582 */
2583 if (ret_srk_buf) {
2584 log_debug("Serializing SRK ESYS_TR reference");
d9a1f1a7 2585 rc = sym_Esys_TR_Serialize(c->esys_context, primary_handle->esys_handle, &srk_buf, &srk_buf_size);
acbb504e
WR
2586 if (rc != TSS2_RC_SUCCESS)
2587 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2588 "Failed to serialize primary key: %s", sym_Tss2_RC_Decode(rc));
2589 }
2590
5291f26d
ZJS
2591 if (DEBUG_LOGGING)
2592 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624 2593
acbb504e
WR
2594 if (ret_srk_buf) {
2595 /*
2596 * make a copy since we don't want the caller to understand that
2597 * ESYS allocated the pointer. It would make tracking what deallocator
2598 * to use for srk_buf in which context a PITA.
2599 */
2600 void *tmp = memdup(srk_buf, srk_buf_size);
2601 if (!tmp)
2602 return log_oom();
2603
2604 *ret_srk_buf = TAKE_PTR(tmp);
2605 *ret_srk_buf_size = srk_buf_size;
2606 }
2607
5e521624
LP
2608 *ret_secret = TAKE_PTR(secret);
2609 *ret_secret_size = hmac_sensitive.sensitive.data.size;
2610 *ret_blob = TAKE_PTR(blob);
2611 *ret_blob_size = blob_size;
2612 *ret_pcr_hash = TAKE_PTR(hash);
d9a1f1a7 2613 *ret_pcr_hash_size = policy_digest.size;
07697bfe 2614 *ret_pcr_bank = pcr_bank;
2b92a672 2615 *ret_primary_alg = primary_alg;
5e521624 2616
16e16b8c 2617 return 0;
5e521624
LP
2618}
2619
0254e4d6
AAF
2620#define RETRY_UNSEAL_MAX 30u
2621
d9b5841d
LP
2622int tpm2_unseal(const char *device,
2623 uint32_t hash_pcr_mask,
07697bfe 2624 uint16_t pcr_bank,
d9b5841d
LP
2625 const void *pubkey,
2626 size_t pubkey_size,
2627 uint32_t pubkey_pcr_mask,
2628 JsonVariant *signature,
2629 const char *pin,
2b92a672 2630 uint16_t primary_alg,
5e521624
LP
2631 const void *blob,
2632 size_t blob_size,
2633 const void *known_policy_hash,
2634 size_t known_policy_hash_size,
acbb504e
WR
2635 const void *srk_buf,
2636 size_t srk_buf_size,
5e521624
LP
2637 void **ret_secret,
2638 size_t *ret_secret_size) {
2639
5e521624 2640 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
5e521624
LP
2641 _cleanup_(erase_and_freep) char *secret = NULL;
2642 TPM2B_PRIVATE private = {};
2643 TPM2B_PUBLIC public = {};
2644 size_t offset = 0;
2645 TSS2_RC rc;
2646 usec_t start;
2647 int r;
2648
2649 assert(blob);
2650 assert(blob_size > 0);
2651 assert(known_policy_hash_size == 0 || known_policy_hash);
d9b5841d 2652 assert(pubkey_size == 0 || pubkey);
5e521624
LP
2653 assert(ret_secret);
2654 assert(ret_secret_size);
2655
d9b5841d
LP
2656 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
2657 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624 2658
1b30720c
LP
2659 r = dlopen_tpm2();
2660 if (r < 0)
2661 return log_error_errno(r, "TPM2 support is not installed.");
2662
5e521624 2663 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
dc176813
ZJS
2664 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
2665 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
2666 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
2667 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
2668 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5e521624
LP
2669 * and use it to unlock the LUKS2 volume. */
2670
2671 start = now(CLOCK_MONOTONIC);
2672
2673 log_debug("Unmarshalling private part of HMAC key.");
2674
2675 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
2676 if (rc != TSS2_RC_SUCCESS)
2677 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2678 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
2679
2680 log_debug("Unmarshalling public part of HMAC key.");
2681
2682 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
2683 if (rc != TSS2_RC_SUCCESS)
2684 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2685 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
2686
68d084ce
DS
2687 _cleanup_tpm2_context_ Tpm2Context *c = NULL;
2688 r = tpm2_context_new(device, &c);
5e521624
LP
2689 if (r < 0)
2690 return r;
2691
acbb504e 2692 /* If their is a primary key we trust, like an SRK, use it */
16e16b8c 2693 _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
acbb504e
WR
2694 if (srk_buf) {
2695
2696 r = tpm2_handle_new(c, &primary);
2697 if (r < 0)
2698 return r;
2699
2700 primary->keep = true;
2701
2702 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
2703 rc = sym_Esys_TR_Deserialize(
2704 c->esys_context,
2705 srk_buf,
2706 srk_buf_size,
2707 &primary->esys_handle);
2708 if (rc != TSS2_RC_SUCCESS)
2709 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2710 "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc));
2711 /* old callers without an SRK still need to create a key */
2712 } else {
2713 r = tpm2_make_primary(c, primary_alg, false, NULL, &primary);
2714 if (r < 0)
2715 return r;
2716 }
da29de23 2717
5e521624
LP
2718 log_debug("Loading HMAC key into TPM.");
2719
0e15c14f
WR
2720 /*
2721 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
acbb504e
WR
2722 * gives you back a different key, the session initiation will fail. In the
2723 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
2724 * provides protections.
0e15c14f 2725 */
16e16b8c
DS
2726 _cleanup_tpm2_handle_ Tpm2Handle *hmac_key = NULL;
2727 r = tpm2_handle_new(c, &hmac_key);
2728 if (r < 0)
2729 return r;
2730
5e521624 2731 rc = sym_Esys_Load(
68d084ce 2732 c->esys_context,
16e16b8c 2733 primary->esys_handle,
0e15c14f 2734 ESYS_TR_PASSWORD,
5e521624
LP
2735 ESYS_TR_NONE,
2736 ESYS_TR_NONE,
2737 &private,
2738 &public,
16e16b8c 2739 &hmac_key->esys_handle);
5e521624 2740 if (rc != TSS2_RC_SUCCESS) {
2f5a892a
GG
2741 /* If we're in dictionary attack lockout mode, we should see a lockout error here, which we
2742 * need to translate for the caller. */
2743 if (rc == TPM2_RC_LOCKOUT)
16e16b8c 2744 return log_error_errno(
2f5a892a
GG
2745 SYNTHETIC_ERRNO(ENOLCK),
2746 "TPM2 device is in dictionary attack lockout mode.");
2747 else
16e16b8c 2748 return log_error_errno(
2f5a892a
GG
2749 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2750 "Failed to load HMAC key in TPM: %s",
2751 sym_Tss2_RC_Decode(rc));
5e521624
LP
2752 }
2753
524cef3f
DS
2754 TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
2755 _cleanup_free_ void *fp = NULL;
2756 size_t fp_size = 0;
2757 if (pubkey) {
2758 r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
2759 if (r < 0)
2760 return r;
2761 authorize_key = &pubkey_tpm2;
2762 }
2763
409a65f8
DS
2764 /*
2765 * if a pin is set for the seal object, use it to bind the session
2766 * key to that object. This prevents active bus interposers from
2767 * faking a TPM and seeing the unsealed value. An active interposer
2768 * could fake a TPM, satisfying the encrypted session, and just
2769 * forward everything to the *real* TPM.
2770 */
2771 r = tpm2_set_auth(c, hmac_key, pin);
2772 if (r < 0)
2773 return r;
2774
2cd9d575 2775 _cleanup_tpm2_handle_ Tpm2Handle *encryption_session = NULL;
409a65f8 2776 r = tpm2_make_encryption_session(c, primary, hmac_key, &encryption_session);
0e15c14f 2777 if (r < 0)
16e16b8c 2778 return r;
2f5a892a 2779
0254e4d6 2780 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
16e16b8c 2781 _cleanup_tpm2_handle_ Tpm2Handle *policy_session = NULL;
23b972d5 2782 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
0254e4d6 2783 r = tpm2_make_policy_session(
23e9ccc2 2784 c,
0254e4d6 2785 primary,
2cd9d575
DS
2786 encryption_session,
2787 /* trial= */ false,
2788 &policy_session);
2789 if (r < 0)
2790 return r;
2791
2792 r = tpm2_build_sealing_policy(
2793 c,
2794 policy_session,
0254e4d6
AAF
2795 hash_pcr_mask,
2796 pcr_bank,
524cef3f
DS
2797 authorize_key,
2798 fp, fp_size,
0254e4d6
AAF
2799 pubkey_pcr_mask,
2800 signature,
2801 !!pin,
2cd9d575 2802 &policy_digest);
0254e4d6 2803 if (r < 0)
16e16b8c 2804 return r;
2f5a892a 2805
0254e4d6
AAF
2806 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
2807 * wait until the TPM2 tells us to go away. */
2808 if (known_policy_hash_size > 0 &&
2809 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
2810 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
2811 "Current policy digest does not match stored policy digest, cancelling "
2812 "TPM2 authentication attempt.");
2f5a892a 2813
0254e4d6 2814 log_debug("Unsealing HMAC key.");
5e521624 2815
0254e4d6 2816 rc = sym_Esys_Unseal(
68d084ce 2817 c->esys_context,
16e16b8c
DS
2818 hmac_key->esys_handle,
2819 policy_session->esys_handle,
2cd9d575 2820 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
0254e4d6
AAF
2821 ESYS_TR_NONE,
2822 &unsealed);
16e16b8c
DS
2823 if (rc == TSS2_RC_SUCCESS)
2824 break;
2825 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
2826 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2827 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
2828 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5e521624
LP
2829 }
2830
2831 secret = memdup(unsealed->buffer, unsealed->size);
2832 explicit_bzero_safe(unsealed->buffer, unsealed->size);
16e16b8c
DS
2833 if (!secret)
2834 return log_oom();
5e521624 2835
5291f26d
ZJS
2836 if (DEBUG_LOGGING)
2837 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624
LP
2838
2839 *ret_secret = TAKE_PTR(secret);
2840 *ret_secret_size = unsealed->size;
2841
16e16b8c 2842 return 0;
5e521624
LP
2843}
2844
2845#endif
2846
2847int tpm2_list_devices(void) {
2848#if HAVE_TPM2
2849 _cleanup_(table_unrefp) Table *t = NULL;
2850 _cleanup_(closedirp) DIR *d = NULL;
2851 int r;
2852
2853 r = dlopen_tpm2();
2854 if (r < 0)
2855 return log_error_errno(r, "TPM2 support is not installed.");
2856
2857 t = table_new("path", "device", "driver");
2858 if (!t)
2859 return log_oom();
2860
2861 d = opendir("/sys/class/tpmrm");
2862 if (!d) {
2863 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
2864 if (errno != ENOENT)
2865 return -errno;
2866 } else {
2867 for (;;) {
2868 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
2869 struct dirent *de;
2870
2871 de = readdir_no_dot(d);
2872 if (!de)
2873 break;
2874
2875 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
2876 if (!device_path)
2877 return log_oom();
2878
2879 r = readlink_malloc(device_path, &device);
2880 if (r < 0)
2881 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
2882 else {
2883 driver_path = path_join(device_path, "driver");
2884 if (!driver_path)
2885 return log_oom();
2886
2887 r = readlink_malloc(driver_path, &driver);
2888 if (r < 0)
2889 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
2890 }
2891
2892 node = path_join("/dev", de->d_name);
2893 if (!node)
2894 return log_oom();
2895
2896 r = table_add_many(
2897 t,
2898 TABLE_PATH, node,
2899 TABLE_STRING, device ? last_path_component(device) : NULL,
2900 TABLE_STRING, driver ? last_path_component(driver) : NULL);
2901 if (r < 0)
2902 return table_log_add_error(r);
2903 }
2904 }
2905
2906 if (table_get_rows(t) <= 1) {
2907 log_info("No suitable TPM2 devices found.");
2908 return 0;
2909 }
2910
2911 r = table_print(t, stdout);
2912 if (r < 0)
2913 return log_error_errno(r, "Failed to show device table: %m");
2914
2915 return 0;
2916#else
2917 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2918 "TPM2 not supported on this build.");
2919#endif
2920}
2921
2922int tpm2_find_device_auto(
2923 int log_level, /* log level when no device is found */
2924 char **ret) {
2925#if HAVE_TPM2
2926 _cleanup_(closedirp) DIR *d = NULL;
2927 int r;
2928
2929 r = dlopen_tpm2();
2930 if (r < 0)
2931 return log_error_errno(r, "TPM2 support is not installed.");
2932
2933 d = opendir("/sys/class/tpmrm");
2934 if (!d) {
2935 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
2936 "Failed to open /sys/class/tpmrm: %m");
2937 if (errno != ENOENT)
2938 return -errno;
2939 } else {
2940 _cleanup_free_ char *node = NULL;
2941
2942 for (;;) {
2943 struct dirent *de;
2944
2945 de = readdir_no_dot(d);
2946 if (!de)
2947 break;
2948
2949 if (node)
2950 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
2951 "More than one TPM2 (tpmrm) device found.");
2952
2953 node = path_join("/dev", de->d_name);
2954 if (!node)
2955 return log_oom();
2956 }
2957
2958 if (node) {
2959 *ret = TAKE_PTR(node);
2960 return 0;
2961 }
2962 }
2963
2964 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
2965#else
2966 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2967 "TPM2 not supported on this build.");
2968#endif
2969}
2970
15c591d1
LP
2971#if HAVE_TPM2
2972int tpm2_extend_bytes(
23e9ccc2 2973 Tpm2Context *c,
15c591d1
LP
2974 char **banks,
2975 unsigned pcr_index,
2976 const void *data,
9885c874
LP
2977 size_t data_size,
2978 const void *secret,
2979 size_t secret_size) {
15c591d1
LP
2980
2981#if HAVE_OPENSSL
2982 TPML_DIGEST_VALUES values = {};
2983 TSS2_RC rc;
2984
2985 assert(c);
9885c874
LP
2986 assert(data || data_size == 0);
2987 assert(secret || secret_size == 0);
2988
2989 if (data_size == SIZE_MAX)
2990 data_size = strlen(data);
2991 if (secret_size == SIZE_MAX)
2992 secret_size = strlen(secret);
15c591d1
LP
2993
2994 if (pcr_index >= TPM2_PCRS_MAX)
2995 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
2996
2997 if (strv_isempty(banks))
2998 return 0;
2999
3000 STRV_FOREACH(bank, banks) {
3001 const EVP_MD *implementation;
3002 int id;
3003
3004 assert_se(implementation = EVP_get_digestbyname(*bank));
3005
3006 if (values.count >= ELEMENTSOF(values.digests))
3007 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
3008
3009 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
3010 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
3011
7bfe0a48 3012 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
15c591d1
LP
3013 if (id < 0)
3014 return log_error_errno(id, "Can't map hash name to TPM2.");
3015
3016 values.digests[values.count].hashAlg = id;
3017
9885c874
LP
3018 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
3019 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
3020 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
3021 * secret for other purposes, maybe because it needs a shorter secret derived from it for
3022 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
3023 * private non-secret string instead. */
3024 if (secret_size > 0) {
3025 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
3026 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
3027 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
3028 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
15c591d1
LP
3029
3030 values.count++;
3031 }
3032
3033 rc = sym_Esys_PCR_Extend(
23e9ccc2 3034 c->esys_context,
15c591d1
LP
3035 ESYS_TR_PCR0 + pcr_index,
3036 ESYS_TR_PASSWORD,
3037 ESYS_TR_NONE,
3038 ESYS_TR_NONE,
3039 &values);
3040 if (rc != TSS2_RC_SUCCESS)
3041 return log_error_errno(
3042 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3043 "Failed to measure into PCR %u: %s",
3044 pcr_index,
3045 sym_Tss2_RC_Decode(rc));
3046
3047 return 0;
0d7009d3
DS
3048#else /* HAVE_OPENSSL */
3049 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
15c591d1
LP
3050#endif
3051}
3052#endif
3053
c69bd0ab
DS
3054char *tpm2_pcr_mask_to_string(uint32_t mask) {
3055 _cleanup_free_ char *s = NULL;
3056
3057 FOREACH_PCR_IN_MASK(n, mask)
3058 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
3059 return NULL;
3060
3061 if (!s)
3062 return strdup("");
3063
3064 return TAKE_PTR(s);
3065}
3066
3067int tpm2_pcr_mask_from_string(const char *arg, uint32_t *ret_mask) {
5e521624
LP
3068 uint32_t mask = 0;
3069 int r;
3070
c69bd0ab
DS
3071 assert(arg);
3072 assert(ret_mask);
3073
3074 if (isempty(arg)) {
3075 *ret_mask = 0;
d57f6340
LP
3076 return 0;
3077 }
3078
a1788a69
LP
3079 /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
3080 * and most other tools expect comma separated PCR specifications. We also support "+" since in
3081 * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
3082 * avoid escaping. */
5e521624 3083
c69bd0ab 3084 const char *p = arg;
5e521624
LP
3085 for (;;) {
3086 _cleanup_free_ char *pcr = NULL;
3087 unsigned n;
3088
a1788a69 3089 r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
5e521624
LP
3090 if (r == 0)
3091 break;
3092 if (r < 0)
c69bd0ab 3093 return log_error_errno(r, "Failed to parse PCR list: %s", arg);
5e521624 3094
96ead603 3095 r = pcr_index_from_string(pcr);
5e521624 3096 if (r < 0)
96ead603
OJ
3097 return log_error_errno(r, "Failed to parse specified PCR or specified PCR is out of range: %s", pcr);
3098 n = r;
c69bd0ab 3099 SET_BIT(mask, n);;
5e521624
LP
3100 }
3101
c69bd0ab 3102 *ret_mask = mask;
5e521624
LP
3103 return 0;
3104}
3105
4436081e
LP
3106int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
3107 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
3108 JsonVariant* pcr_array[TPM2_PCRS_MAX];
3109 unsigned n_pcrs = 0;
3110 int r;
3111
3112 for (size_t i = 0; i < ELEMENTSOF(pcr_array); i++) {
3113 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
3114 continue;
3115
3116 r = json_variant_new_integer(pcr_array + n_pcrs, i);
3117 if (r < 0)
3118 goto finish;
3119
3120 n_pcrs++;
3121 }
3122
3123 r = json_variant_new_array(&a, pcr_array, n_pcrs);
3124 if (r < 0)
3125 goto finish;
3126
3127 if (ret)
3128 *ret = TAKE_PTR(a);
3129 r = 0;
3130
3131finish:
3132 json_variant_unref_many(pcr_array, n_pcrs);
3133 return r;
3134}
8de8ec88
LP
3135
3136int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
3137 JsonVariant *e;
3138 uint32_t mask = 0;
3139
3140 if (!json_variant_is_array(v))
3141 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
3142
3143 JSON_VARIANT_ARRAY_FOREACH(e, v) {
3144 uint64_t u;
3145
3146 if (!json_variant_is_unsigned(e))
3147 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
3148
3149 u = json_variant_unsigned(e);
3150 if (u >= TPM2_PCRS_MAX)
3151 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
3152
3153 mask |= UINT32_C(1) << u;
3154 }
3155
3156 if (ret)
3157 *ret = mask;
3158
3159 return 0;
3160}
4436081e 3161
5e521624
LP
3162int tpm2_make_luks2_json(
3163 int keyslot,
f0f4fcae 3164 uint32_t hash_pcr_mask,
07697bfe 3165 uint16_t pcr_bank,
f0f4fcae
LP
3166 const void *pubkey,
3167 size_t pubkey_size,
3168 uint32_t pubkey_pcr_mask,
2b92a672 3169 uint16_t primary_alg,
5e521624
LP
3170 const void *blob,
3171 size_t blob_size,
3172 const void *policy_hash,
3173 size_t policy_hash_size,
aae6eb96
WR
3174 const void *salt,
3175 size_t salt_size,
acbb504e
WR
3176 const void *srk_buf,
3177 size_t srk_buf_size,
6c7a1681 3178 TPM2Flags flags,
5e521624
LP
3179 JsonVariant **ret) {
3180
f0f4fcae 3181 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
5e521624 3182 _cleanup_free_ char *keyslot_as_string = NULL;
5e521624
LP
3183 int r;
3184
3185 assert(blob || blob_size == 0);
3186 assert(policy_hash || policy_hash_size == 0);
f0f4fcae 3187 assert(pubkey || pubkey_size == 0);
5e521624
LP
3188
3189 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
3190 return -ENOMEM;
3191
f0f4fcae 3192 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
5e521624 3193 if (r < 0)
4436081e 3194 return r;
5e521624 3195
f0f4fcae
LP
3196 if (pubkey_pcr_mask != 0) {
3197 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
3198 if (r < 0)
3199 return r;
3200 }
3201
3202 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
3203 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
3204 * object should use "_" rather than "-" in field names. */
3205
5e521624
LP
3206 r = json_build(&v,
3207 JSON_BUILD_OBJECT(
0cdf6b14 3208 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
5e521624
LP
3209 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
3210 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
f0f4fcae 3211 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7bfe0a48
DS
3212 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
3213 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 3214 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
f0f4fcae
LP
3215 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
3216 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
aae6eb96 3217 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
acbb504e
WR
3218 JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size)),
3219 JSON_BUILD_PAIR_CONDITION(srk_buf, "tpm2_srk", JSON_BUILD_BASE64(srk_buf, srk_buf_size))));
5e521624
LP
3220 if (r < 0)
3221 return r;
3222
3223 if (ret)
3224 *ret = TAKE_PTR(v);
3225
3226 return keyslot;
3227}
07697bfe 3228
fdf6c27c
LP
3229int tpm2_parse_luks2_json(
3230 JsonVariant *v,
3231 int *ret_keyslot,
3232 uint32_t *ret_hash_pcr_mask,
3233 uint16_t *ret_pcr_bank,
3234 void **ret_pubkey,
3235 size_t *ret_pubkey_size,
3236 uint32_t *ret_pubkey_pcr_mask,
3237 uint16_t *ret_primary_alg,
3238 void **ret_blob,
3239 size_t *ret_blob_size,
3240 void **ret_policy_hash,
3241 size_t *ret_policy_hash_size,
aae6eb96
WR
3242 void **ret_salt,
3243 size_t *ret_salt_size,
acbb504e
WR
3244 void **ret_srk_buf,
3245 size_t *ret_srk_buf_size,
fdf6c27c
LP
3246 TPM2Flags *ret_flags) {
3247
acbb504e
WR
3248 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
3249 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
fdf6c27c
LP
3250 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
3251 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
3252 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
3253 int r, keyslot = -1;
3254 TPM2Flags flags = 0;
3255 JsonVariant *w;
3256
3257 assert(v);
3258
3259 if (ret_keyslot) {
3260 keyslot = cryptsetup_get_keyslot_from_token(v);
3261 if (keyslot < 0) {
3262 /* Return a recognizable error when parsing this field, so that callers can handle parsing
3263 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
3264 * spec */
3265 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
3266 return -EUCLEAN;
3267 }
3268 }
3269
3270 w = json_variant_by_key(v, "tpm2-pcrs");
3271 if (!w)
3272 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
3273
3274 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
3275 if (r < 0)
3276 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
3277
3278 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
3279 * to SHA256. */
3280 w = json_variant_by_key(v, "tpm2-pcr-bank");
3281 if (w) {
3282 /* The PCR bank field is optional */
3283
3284 if (!json_variant_is_string(w))
3285 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
3286
7bfe0a48 3287 r = tpm2_hash_alg_from_string(json_variant_string(w));
fdf6c27c
LP
3288 if (r < 0)
3289 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
3290
3291 pcr_bank = r;
3292 }
3293
3294 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
3295 * the algorithm was hardcoded to ECC. */
3296 w = json_variant_by_key(v, "tpm2-primary-alg");
3297 if (w) {
3298 /* The primary key algorithm is optional */
3299
3300 if (!json_variant_is_string(w))
3301 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
3302
7bfe0a48 3303 r = tpm2_asym_alg_from_string(json_variant_string(w));
fdf6c27c 3304 if (r < 0)
7bfe0a48 3305 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
fdf6c27c
LP
3306
3307 primary_alg = r;
3308 }
3309
3310 w = json_variant_by_key(v, "tpm2-blob");
3311 if (!w)
3312 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
3313
3314 r = json_variant_unbase64(w, &blob, &blob_size);
3315 if (r < 0)
3316 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
3317
3318 w = json_variant_by_key(v, "tpm2-policy-hash");
3319 if (!w)
3320 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
3321
3322 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
3323 if (r < 0)
3324 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
3325
3326 w = json_variant_by_key(v, "tpm2-pin");
3327 if (w) {
3328 if (!json_variant_is_boolean(w))
3329 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
3330
3331 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
3332 }
3333
aae6eb96
WR
3334 w = json_variant_by_key(v, "tpm2_salt");
3335 if (w) {
3336 r = json_variant_unbase64(w, &salt, &salt_size);
3337 if (r < 0)
3338 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
3339 }
3340
fdf6c27c
LP
3341 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
3342 if (w) {
3343 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
3344 if (r < 0)
3345 return r;
3346 }
3347
3348 w = json_variant_by_key(v, "tpm2_pubkey");
3349 if (w) {
3350 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
3351 if (r < 0)
3352 return log_debug_errno(r, "Failed to decode PCR public key.");
3353 } else if (pubkey_pcr_mask != 0)
3354 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
3355
acbb504e
WR
3356 w = json_variant_by_key(v, "tpm2_srk");
3357 if (w) {
3358 r = json_variant_unbase64(w, &srk_buf, &srk_buf_size);
3359 if (r < 0)
3360 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
3361 }
3362
fdf6c27c
LP
3363 if (ret_keyslot)
3364 *ret_keyslot = keyslot;
3365 if (ret_hash_pcr_mask)
3366 *ret_hash_pcr_mask = hash_pcr_mask;
3367 if (ret_pcr_bank)
3368 *ret_pcr_bank = pcr_bank;
3369 if (ret_pubkey)
3370 *ret_pubkey = TAKE_PTR(pubkey);
3371 if (ret_pubkey_size)
3372 *ret_pubkey_size = pubkey_size;
3373 if (ret_pubkey_pcr_mask)
3374 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
3375 if (ret_primary_alg)
3376 *ret_primary_alg = primary_alg;
3377 if (ret_blob)
3378 *ret_blob = TAKE_PTR(blob);
3379 if (ret_blob_size)
3380 *ret_blob_size = blob_size;
3381 if (ret_policy_hash)
3382 *ret_policy_hash = TAKE_PTR(policy_hash);
3383 if (ret_policy_hash_size)
3384 *ret_policy_hash_size = policy_hash_size;
aae6eb96
WR
3385 if (ret_salt)
3386 *ret_salt = TAKE_PTR(salt);
3387 if (ret_salt_size)
3388 *ret_salt_size = salt_size;
fdf6c27c
LP
3389 if (ret_flags)
3390 *ret_flags = flags;
acbb504e
WR
3391 if (ret_srk_buf)
3392 *ret_srk_buf = TAKE_PTR(srk_buf);
3393 if (ret_srk_buf_size)
3394 *ret_srk_buf_size = srk_buf_size;
fdf6c27c
LP
3395
3396 return 0;
3397}
3398
7bfe0a48
DS
3399const char *tpm2_hash_alg_to_string(uint16_t alg) {
3400 if (alg == TPM2_ALG_SHA1)
07697bfe 3401 return "sha1";
7bfe0a48 3402 if (alg == TPM2_ALG_SHA256)
98193c39 3403 return "sha256";
7bfe0a48 3404 if (alg == TPM2_ALG_SHA384)
98193c39 3405 return "sha384";
7bfe0a48 3406 if (alg == TPM2_ALG_SHA512)
98193c39 3407 return "sha512";
07697bfe
LP
3408 return NULL;
3409}
3410
7bfe0a48
DS
3411int tpm2_hash_alg_from_string(const char *alg) {
3412 if (strcaseeq_ptr(alg, "sha1"))
07697bfe 3413 return TPM2_ALG_SHA1;
7bfe0a48 3414 if (strcaseeq_ptr(alg, "sha256"))
98193c39 3415 return TPM2_ALG_SHA256;
7bfe0a48 3416 if (strcaseeq_ptr(alg, "sha384"))
98193c39 3417 return TPM2_ALG_SHA384;
7bfe0a48 3418 if (strcaseeq_ptr(alg, "sha512"))
98193c39 3419 return TPM2_ALG_SHA512;
07697bfe
LP
3420 return -EINVAL;
3421}
2b92a672 3422
7bfe0a48 3423const char *tpm2_asym_alg_to_string(uint16_t alg) {
2b92a672
LP
3424 if (alg == TPM2_ALG_ECC)
3425 return "ecc";
3426 if (alg == TPM2_ALG_RSA)
3427 return "rsa";
3428 return NULL;
3429}
3430
7bfe0a48 3431int tpm2_asym_alg_from_string(const char *alg) {
f92ebc86 3432 if (strcaseeq_ptr(alg, "ecc"))
2b92a672 3433 return TPM2_ALG_ECC;
f92ebc86 3434 if (strcaseeq_ptr(alg, "rsa"))
2b92a672
LP
3435 return TPM2_ALG_RSA;
3436 return -EINVAL;
3437}
ba578556
LP
3438
3439Tpm2Support tpm2_support(void) {
3440 Tpm2Support support = TPM2_SUPPORT_NONE;
3441 int r;
3442
44d5dd65
LP
3443 if (detect_container() <= 0) {
3444 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
3445 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
3446 * let's assume containers never have a TPM, at least for now. */
3447
db55bbf2 3448 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
44d5dd65
LP
3449 if (r < 0) {
3450 if (r != -ENOENT)
3451 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
3452 } else if (r == 0) /* populated! */
300bba79
DDM
3453 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
3454 else
3455 /* If the directory exists but is empty, we know the subsystem is enabled but no
3456 * driver has been loaded yet. */
3457 support |= TPM2_SUPPORT_SUBSYSTEM;
44d5dd65 3458 }
ba578556
LP
3459
3460 if (efi_has_tpm2())
3461 support |= TPM2_SUPPORT_FIRMWARE;
3462
3463#if HAVE_TPM2
3464 support |= TPM2_SUPPORT_SYSTEM;
3465#endif
3466
3467 return support;
3468}
222a951f
LP
3469
3470int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask) {
3471 uint32_t m;
3472 int r;
3473
3474 assert(mask);
3475
3476 /* For use in getopt_long() command line parsers: merges masks specified on the command line */
3477
3478 if (isempty(arg)) {
3479 *mask = 0;
3480 return 0;
3481 }
3482
c69bd0ab 3483 r = tpm2_pcr_mask_from_string(arg, &m);
222a951f
LP
3484 if (r < 0)
3485 return r;
3486
3487 if (*mask == UINT32_MAX)
3488 *mask = m;
3489 else
3490 *mask |= m;
3491
3492 return 0;
3493}
6a0779cb
LP
3494
3495int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
3496 _cleanup_free_ char *discovered_path = NULL;
3497 _cleanup_fclose_ FILE *f = NULL;
3498 int r;
3499
3500 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
3501 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
3502
3503 if (!path)
3504 path = "tpm2-pcr-signature.json";
3505
3506 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
3507 if (r < 0)
3508 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
3509
3510 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
3511 if (r < 0)
3512 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
3513
3514 return 0;
3515}
3516
3517int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
3518 _cleanup_free_ char *discovered_path = NULL;
3519 _cleanup_fclose_ FILE *f = NULL;
3520 int r;
3521
3522 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
3523 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
3524
3525 if (!path)
3526 path = "tpm2-pcr-public-key.pem";
3527
3528 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
3529 if (r < 0)
3530 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
3531
3532 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
3533 if (r < 0)
3534 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
3535
3536 return 0;
3537}
4d5cc0d4 3538
aae6eb96
WR
3539#define PBKDF2_HMAC_SHA256_ITERATIONS 10000
3540
3541/*
3542 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
3543 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
3544 * I found the wikipedia entry relevant and it contains links to
3545 * relevant RFCs:
3546 * - https://en.wikipedia.org/wiki/PBKDF2
3547 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
3548 */
3549int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
3550 size_t passlen,
3551 const void *salt,
3552 size_t saltlen,
3553 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
3554
3555 uint8_t _cleanup_(erase_and_freep) *buffer = NULL;
3556 uint8_t u[SHA256_DIGEST_SIZE];
3557
3558 /* To keep this simple, since derived KeyLen (dkLen in docs)
3559 * Is the same as the hash output, we don't need multiple
3560 * blocks. Part of the algorithm is to add the block count
3561 * in, but this can be hardcoded to 1.
3562 */
3563 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
3564
504d0acf 3565 assert (salt);
aae6eb96
WR
3566 assert (saltlen > 0);
3567 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
3568 assert (passlen > 0);
3569
3570 /*
3571 * Build a buffer of salt + block_cnt and hmac_sha256 it we
3572 * do this as we don't have a context builder for HMAC_SHA256.
3573 */
3574 buffer = malloc(saltlen + sizeof(block_cnt));
3575 if (!buffer)
3576 return -ENOMEM;
3577
3578 memcpy(buffer, salt, saltlen);
3579 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
3580
3581 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
3582
3583 /* dk needs to be an unmodified u as u gets modified in the loop */
3584 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
3585 uint8_t *dk = ret_key;
3586
3587 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
3588 hmac_sha256(pass, passlen, u, sizeof(u), u);
3589
3590 for (size_t j=0; j < sizeof(u); j++)
3591 dk[j] ^= u[j];
3592 }
3593
3594 return 0;
3595}
96ead603
OJ
3596
3597static const char* const pcr_index_table[_PCR_INDEX_MAX_DEFINED] = {
3598 [PCR_PLATFORM_CODE] = "platform-code",
3599 [PCR_PLATFORM_CONFIG] = "platform-config",
3600 [PCR_EXTERNAL_CODE] = "external-code",
3601 [PCR_EXTERNAL_CONFIG] = "external-config",
3602 [PCR_BOOT_LOADER_CODE] = "boot-loader-code",
3603 [PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
3604 [PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
3605 [PCR_KERNEL_INITRD] = "kernel-initrd",
3606 [PCR_IMA] = "ima",
3607 [PCR_KERNEL_BOOT] = "kernel-boot",
3608 [PCR_KERNEL_CONFIG] = "kernel-config",
3609 [PCR_SYSEXTS] = "sysexts",
3610 [PCR_SHIM_POLICY] = "shim-policy",
3611 [PCR_SYSTEM_IDENTITY] = "system-identity",
3612 [PCR_DEBUG] = "debug",
3613 [PCR_APPLICATION_SUPPORT] = "application-support",
3614};
3615
d685a5f6 3616DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(pcr_index, int, TPM2_PCRS_MAX - 1);