]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/tpm2-util.c
test/test-bitfield: add tests for bitfield macros
[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"
5e521624 16#include "memory-util.h"
d9b5841d 17#include "openssl-util.h"
fdf6c27c 18#include "parse-util.h"
5e521624 19#include "random-util.h"
2f5a892a 20#include "sha256.h"
fdf6c27c 21#include "stat-util.h"
5e521624 22#include "time-util.h"
fdf6c27c
LP
23#include "tpm2-util.h"
24#include "virt.h"
5e521624 25
fdf6c27c 26#if HAVE_TPM2
5e521624
LP
27static void *libtss2_esys_dl = NULL;
28static void *libtss2_rc_dl = NULL;
29static void *libtss2_mu_dl = NULL;
30
31TSS2_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;
32TSS2_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;
33void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
34TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
35void (*sym_Esys_Free)(void *ptr) = NULL;
07697bfe 36TSS2_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);
5e521624
LP
37TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
38TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
39TSS2_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;
0d756413 40TSS2_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);
1421943a 41TSS2_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);
321a9d9e 42TSS2_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);
0d756413 43TSS2_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);
2f5a892a 44TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
5e521624
LP
45TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
46TSS2_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;
47TSS2_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;
48TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
da29de23 49TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask);
0d756413 50TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name);
2f5a892a 51TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
5e521624 52TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
0d756413 53TSS2_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);
5e521624
LP
54
55const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
56
57TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
58TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
59TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
60TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
61
62int dlopen_tpm2(void) {
d32f7a8e
ZJS
63 int r;
64
65 r = dlopen_many_sym_or_warn(
66 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
67 DLSYM_ARG(Esys_Create),
68 DLSYM_ARG(Esys_CreatePrimary),
69 DLSYM_ARG(Esys_Finalize),
70 DLSYM_ARG(Esys_FlushContext),
71 DLSYM_ARG(Esys_Free),
07697bfe 72 DLSYM_ARG(Esys_GetCapability),
d32f7a8e
ZJS
73 DLSYM_ARG(Esys_GetRandom),
74 DLSYM_ARG(Esys_Initialize),
75 DLSYM_ARG(Esys_Load),
0d756413 76 DLSYM_ARG(Esys_LoadExternal),
1421943a 77 DLSYM_ARG(Esys_PCR_Extend),
321a9d9e 78 DLSYM_ARG(Esys_PCR_Read),
0d756413 79 DLSYM_ARG(Esys_PolicyAuthorize),
2f5a892a 80 DLSYM_ARG(Esys_PolicyAuthValue),
d32f7a8e
ZJS
81 DLSYM_ARG(Esys_PolicyGetDigest),
82 DLSYM_ARG(Esys_PolicyPCR),
83 DLSYM_ARG(Esys_StartAuthSession),
84 DLSYM_ARG(Esys_Startup),
da29de23 85 DLSYM_ARG(Esys_TRSess_SetAttributes),
0d756413 86 DLSYM_ARG(Esys_TR_GetName),
2f5a892a 87 DLSYM_ARG(Esys_TR_SetAuth),
0d756413
LP
88 DLSYM_ARG(Esys_Unseal),
89 DLSYM_ARG(Esys_VerifySignature));
d32f7a8e
ZJS
90 if (r < 0)
91 return r;
92
93 r = dlopen_many_sym_or_warn(
94 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
95 DLSYM_ARG(Tss2_RC_Decode));
96 if (r < 0)
97 return r;
98
99 return dlopen_many_sym_or_warn(
100 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
101 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
102 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
103 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
104 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal));
5e521624
LP
105}
106
68d084ce
DS
107static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
108 if (!c)
109 return NULL;
5e521624
LP
110
111 if (c->esys_context)
112 sym_Esys_Finalize(&c->esys_context);
113
114 c->tcti_context = mfree(c->tcti_context);
f2592ef0 115 c->tcti_dl = safe_dlclose(c->tcti_dl);
5e521624 116
68d084ce 117 return mfree(c);
5e521624
LP
118}
119
68d084ce
DS
120DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
121
68d084ce
DS
122int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
123 _cleanup_tpm2_context_ Tpm2Context *context = NULL;
5e521624
LP
124 TSS2_RC rc;
125 int r;
126
68d084ce
DS
127 assert(ret_context);
128
d70e4bc9 129 context = new(Tpm2Context, 1);
68d084ce
DS
130 if (!context)
131 return log_oom();
132
d70e4bc9
LP
133 *context = (Tpm2Context) {
134 .n_ref = 1,
135 };
68d084ce 136
5e521624
LP
137 r = dlopen_tpm2();
138 if (r < 0)
139 return log_error_errno(r, "TPM2 support not installed: %m");
140
34906680 141 if (!device) {
5e521624 142 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
34906680
LP
143 if (device)
144 /* Setting the env var to an empty string forces tpm2-tss' own device picking
145 * logic to be used. */
146 device = empty_to_null(device);
147 else
148 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
149 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
150 * might be used and we really don't want that, since it is a system service and that creates
151 * various ordering issues/deadlocks during early boot. */
152 device = "device:/dev/tpmrm0";
153 }
5e521624
LP
154
155 if (device) {
156 const char *param, *driver, *fn;
157 const TSS2_TCTI_INFO* info;
158 TSS2_TCTI_INFO_FUNC func;
159 size_t sz = 0;
160
161 param = strchr(device, ':');
162 if (param) {
50a08514 163 /* Syntax #1: Pair of driver string and arbitrary parameter */
2f82562b 164 driver = strndupa_safe(device, param - device);
50a08514
LP
165 if (isempty(driver))
166 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
167
5e521624 168 param++;
50a08514
LP
169 } else if (path_is_absolute(device) && path_is_valid(device)) {
170 /* Syntax #2: TPM device node */
5e521624
LP
171 driver = "device";
172 param = device;
50a08514
LP
173 } else
174 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
175
176 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
5e521624
LP
177
178 fn = strjoina("libtss2-tcti-", driver, ".so.0");
179
50a08514
LP
180 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
181 if (!filename_is_valid(fn))
182 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
183
68d084ce
DS
184 context->tcti_dl = dlopen(fn, RTLD_NOW);
185 if (!context->tcti_dl)
5e521624
LP
186 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
187
68d084ce 188 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
5e521624
LP
189 if (!func)
190 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
191 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
192 dlerror());
193
194 info = func();
195 if (!info)
196 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
197
5e521624
LP
198 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
199
200 rc = info->init(NULL, &sz, NULL);
201 if (rc != TPM2_RC_SUCCESS)
202 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
203 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
204
68d084ce
DS
205 context->tcti_context = malloc0(sz);
206 if (!context->tcti_context)
5e521624
LP
207 return log_oom();
208
68d084ce 209 rc = info->init(context->tcti_context, &sz, param);
5e521624
LP
210 if (rc != TPM2_RC_SUCCESS)
211 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
212 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
213 }
214
68d084ce 215 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
5e521624
LP
216 if (rc != TSS2_RC_SUCCESS)
217 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
218 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
219
68d084ce 220 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
5e521624
LP
221 if (rc == TPM2_RC_INITIALIZE)
222 log_debug("TPM already started up.");
223 else if (rc == TSS2_RC_SUCCESS)
224 log_debug("TPM successfully started up.");
225 else
226 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
227 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
228
68d084ce 229 *ret_context = TAKE_PTR(context);
5e521624
LP
230
231 return 0;
232}
233
16e16b8c
DS
234static void tpm2_handle_flush(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle) {
235 if (!esys_context || esys_handle == ESYS_TR_NONE)
236 return;
237
238 TSS2_RC rc = sym_Esys_FlushContext(esys_context, esys_handle);
239 if (rc != TSS2_RC_SUCCESS) /* We ignore failures here (besides debug logging), since this is called
240 * in error paths, where we cannot do anything about failures anymore. And
241 * when it is called in successful codepaths by this time we already did
242 * what we wanted to do, and got the results we wanted so there's no
243 * reason to make this fail more loudly than necessary. */
244 log_debug("Failed to flush TPM handle, ignoring: %s", sym_Tss2_RC_Decode(rc));
245}
246
247Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
248 if (!handle)
249 return NULL;
250
251 _cleanup_tpm2_context_ Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
252 if (context)
253 tpm2_handle_flush(context->esys_context, handle->esys_handle);
254
255 return mfree(handle);
256}
257
258int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
259 _cleanup_tpm2_handle_ Tpm2Handle *handle = NULL;
260
261 assert(ret_handle);
262
d70e4bc9 263 handle = new(Tpm2Handle, 1);
16e16b8c
DS
264 if (!handle)
265 return log_oom();
266
d70e4bc9
LP
267 *handle = (Tpm2Handle) {
268 .tpm2_context = tpm2_context_ref(context),
269 .esys_handle = ESYS_TR_NONE,
270 };
16e16b8c
DS
271
272 *ret_handle = TAKE_PTR(handle);
273
274 return 0;
275}
276
aba5dac3
LP
277#define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
278
23e9ccc2 279static int tpm2_credit_random(Tpm2Context *c) {
5e521624
LP
280 size_t rps, done = 0;
281 TSS2_RC rc;
aba5dac3 282 usec_t t;
5e521624
LP
283 int r;
284
285 assert(c);
286
287 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
288 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
289 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
290 * any entropy. */
291
aba5dac3
LP
292 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
293 if (errno != ENOENT)
294 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
295 } else {
296 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
297 return 0; /* Already done */
298 }
299
300 t = now(CLOCK_MONOTONIC);
301
5e521624
LP
302 for (rps = random_pool_size(); rps > 0;) {
303 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
304
305 rc = sym_Esys_GetRandom(
23e9ccc2 306 c->esys_context,
5e521624
LP
307 ESYS_TR_NONE,
308 ESYS_TR_NONE,
309 ESYS_TR_NONE,
310 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
311 &buffer);
312 if (rc != TSS2_RC_SUCCESS)
313 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
314 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
315
316 if (buffer->size == 0)
317 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
318 "Zero-sized entropy returned from TPM.");
319
aba5dac3 320 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
5e521624
LP
321 if (r < 0)
322 return log_error_errno(r, "Failed wo write entropy to kernel: %m");
323
324 done += buffer->size;
325 rps = LESS_BY(rps, buffer->size);
326 }
327
aba5dac3
LP
328 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
329
330 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
331 if (r < 0)
332 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
333
5e521624
LP
334 return 0;
335}
336
337static int tpm2_make_primary(
23e9ccc2 338 Tpm2Context *c,
16e16b8c 339 Tpm2Handle **ret_primary,
2b92a672
LP
340 TPMI_ALG_PUBLIC alg,
341 TPMI_ALG_PUBLIC *ret_alg) {
5e521624
LP
342
343 static const TPM2B_SENSITIVE_CREATE primary_sensitive = {};
2b92a672 344 static const TPM2B_PUBLIC primary_template_ecc = {
5e521624
LP
345 .size = sizeof(TPMT_PUBLIC),
346 .publicArea = {
347 .type = TPM2_ALG_ECC,
348 .nameAlg = TPM2_ALG_SHA256,
349 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
55efb33e
LP
350 .parameters.eccDetail = {
351 .symmetric = {
352 .algorithm = TPM2_ALG_AES,
353 .keyBits.aes = 128,
354 .mode.aes = TPM2_ALG_CFB,
5e521624 355 },
55efb33e
LP
356 .scheme.scheme = TPM2_ALG_NULL,
357 .curveID = TPM2_ECC_NIST_P256,
358 .kdf.scheme = TPM2_ALG_NULL,
5e521624
LP
359 },
360 },
361 };
2b92a672
LP
362 static const TPM2B_PUBLIC primary_template_rsa = {
363 .size = sizeof(TPMT_PUBLIC),
364 .publicArea = {
365 .type = TPM2_ALG_RSA,
366 .nameAlg = TPM2_ALG_SHA256,
367 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
55efb33e
LP
368 .parameters.rsaDetail = {
369 .symmetric = {
370 .algorithm = TPM2_ALG_AES,
371 .keyBits.aes = 128,
372 .mode.aes = TPM2_ALG_CFB,
2b92a672 373 },
55efb33e
LP
374 .scheme.scheme = TPM2_ALG_NULL,
375 .keyBits = 2048,
2b92a672
LP
376 },
377 },
378 };
379
5e521624 380 static const TPML_PCR_SELECTION creation_pcr = {};
5e521624 381 TSS2_RC rc;
2b92a672 382 usec_t ts;
16e16b8c 383 int r;
5e521624
LP
384
385 log_debug("Creating primary key on TPM.");
386
2b92a672
LP
387 /* So apparently not all TPM2 devices support ECC. ECC is generally preferably, because it's so much
388 * faster, noticeably so (~10s vs. ~240ms on my system). Hence, unless explicitly configured let's
389 * try to use ECC first, and if that does not work, let's fall back to RSA. */
5e521624 390
2b92a672
LP
391 ts = now(CLOCK_MONOTONIC);
392
16e16b8c
DS
393 _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
394 r = tpm2_handle_new(c, &primary);
395 if (r < 0)
396 return r;
397
2b92a672
LP
398 if (IN_SET(alg, 0, TPM2_ALG_ECC)) {
399 rc = sym_Esys_CreatePrimary(
23e9ccc2 400 c->esys_context,
2b92a672
LP
401 ESYS_TR_RH_OWNER,
402 ESYS_TR_PASSWORD,
403 ESYS_TR_NONE,
404 ESYS_TR_NONE,
405 &primary_sensitive,
406 &primary_template_ecc,
407 NULL,
408 &creation_pcr,
16e16b8c 409 &primary->esys_handle,
2b92a672
LP
410 NULL,
411 NULL,
412 NULL,
413 NULL);
414
415 if (rc != TSS2_RC_SUCCESS) {
416 if (alg != 0)
417 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
418 "Failed to generate ECC primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
419
420 log_debug("Failed to generate ECC primary key in TPM, trying RSA: %s", sym_Tss2_RC_Decode(rc));
421 } else {
422 log_debug("Successfully created ECC primary key on TPM.");
423 alg = TPM2_ALG_ECC;
424 }
425 }
426
427 if (IN_SET(alg, 0, TPM2_ALG_RSA)) {
428 rc = sym_Esys_CreatePrimary(
23e9ccc2 429 c->esys_context,
2b92a672
LP
430 ESYS_TR_RH_OWNER,
431 ESYS_TR_PASSWORD,
432 ESYS_TR_NONE,
433 ESYS_TR_NONE,
434 &primary_sensitive,
435 &primary_template_rsa,
436 NULL,
437 &creation_pcr,
16e16b8c 438 &primary->esys_handle,
2b92a672
LP
439 NULL,
440 NULL,
441 NULL,
442 NULL);
443 if (rc != TSS2_RC_SUCCESS)
444 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
445 "Failed to generate RSA primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
446 else if (alg == 0) {
447 log_notice("TPM2 chip apparently does not support ECC primary keys, falling back to RSA. "
448 "This likely means TPM2 operations will be relatively slow, please be patient.");
449 alg = TPM2_ALG_RSA;
450 }
451
452 log_debug("Successfully created RSA primary key on TPM.");
453 }
5e521624 454
2b92a672 455 log_debug("Generating primary key on TPM2 took %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
5e521624 456
16e16b8c
DS
457 if (ret_primary)
458 *ret_primary = TAKE_PTR(primary);
2b92a672
LP
459 if (ret_alg)
460 *ret_alg = alg;
461
5e521624
LP
462 return 0;
463}
464
bad4c73c 465void tpm2_pcr_mask_to_selection(uint32_t mask, uint16_t bank, TPML_PCR_SELECTION *ret) {
321a9d9e
LP
466 assert(ret);
467
468 /* We only do 24bit here, as that's what PC TPMs are supposed to support */
469 assert(mask <= 0xFFFFFFU);
470
471 *ret = (TPML_PCR_SELECTION) {
472 .count = 1,
4dde902e
LP
473 .pcrSelections[0] = {
474 .hash = bank,
475 .sizeofSelect = 3,
476 .pcrSelect[0] = mask & 0xFF,
477 .pcrSelect[1] = (mask >> 8) & 0xFF,
478 .pcrSelect[2] = (mask >> 16) & 0xFF,
479 }
321a9d9e
LP
480 };
481}
482
483static unsigned find_nth_bit(uint32_t mask, unsigned n) {
484 uint32_t bit = 1;
485
486 assert(n < 32);
487
488 /* Returns the bit index of the nth set bit, e.g. mask=0b101001, n=3 → 5 */
489
490 for (unsigned i = 0; i < sizeof(mask)*8; i++) {
491
492 if (bit & mask) {
493 if (n == 0)
494 return i;
495
496 n--;
497 }
498
499 bit <<= 1;
500 }
501
502 return UINT_MAX;
503}
504
505static int tpm2_pcr_mask_good(
23e9ccc2 506 Tpm2Context *c,
321a9d9e
LP
507 TPMI_ALG_HASH bank,
508 uint32_t mask) {
509
510 _cleanup_(Esys_Freep) TPML_DIGEST *pcr_values = NULL;
511 TPML_PCR_SELECTION selection;
512 bool good = false;
513 TSS2_RC rc;
514
515 assert(c);
516
517 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
518 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
519 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
520
685e3417 521 tpm2_pcr_mask_to_selection(mask, bank, &selection);
321a9d9e
LP
522
523 rc = sym_Esys_PCR_Read(
23e9ccc2 524 c->esys_context,
321a9d9e
LP
525 ESYS_TR_NONE,
526 ESYS_TR_NONE,
527 ESYS_TR_NONE,
528 &selection,
529 NULL,
530 NULL,
531 &pcr_values);
532 if (rc != TSS2_RC_SUCCESS)
533 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
534 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
535
536 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
537 for (unsigned i = 0; i < pcr_values->count; i++) {
538 if (DEBUG_LOGGING) {
539 _cleanup_free_ char *h = NULL;
540 unsigned j;
541
542 h = hexmem(pcr_values->digests[i].buffer, pcr_values->digests[i].size);
543 j = find_nth_bit(mask, i);
544 assert(j != UINT_MAX);
545
546 log_debug("PCR %u value: %s", j, strna(h));
547 }
548
549 if (!memeqbyte(0x00, pcr_values->digests[i].buffer, pcr_values->digests[i].size) &&
550 !memeqbyte(0xFF, pcr_values->digests[i].buffer, pcr_values->digests[i].size))
551 good = true;
552 }
553
554 return good;
555}
556
59fafaee
LP
557static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
558
559 assert(selection);
560
561 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
562 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
563 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
564 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
7bfe0a48 565 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
566 return false;
567 }
568
569 assert_cc(TPM2_PCRS_MAX % 8 == 0);
570
571 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
572 * enabled for this bank. Otherwise this TPM doesn't qualify. */
573 bool valid = true;
574 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
575 if (selection->pcrSelect[j] != 0xFF) {
576 valid = false;
577 break;
578 }
579
580 if (!valid)
581 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
7bfe0a48 582 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
583
584 return valid;
585}
586
07697bfe 587static int tpm2_get_best_pcr_bank(
23e9ccc2 588 Tpm2Context *c,
321a9d9e 589 uint32_t pcr_mask,
07697bfe
LP
590 TPMI_ALG_HASH *ret) {
591
592 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
321a9d9e 593 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
07697bfe
LP
594 TPMI_YES_NO more;
595 TSS2_RC rc;
59fafaee 596 int r;
07697bfe 597
321a9d9e
LP
598 assert(c);
599
07697bfe 600 rc = sym_Esys_GetCapability(
23e9ccc2 601 c->esys_context,
07697bfe
LP
602 ESYS_TR_NONE,
603 ESYS_TR_NONE,
604 ESYS_TR_NONE,
605 TPM2_CAP_PCRS,
606 0,
607 1,
608 &more,
609 &pcap);
610 if (rc != TSS2_RC_SUCCESS)
611 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
612 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
613
614 assert(pcap->capability == TPM2_CAP_PCRS);
615
616 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
321a9d9e
LP
617 int good;
618
619 /* For now we are only interested in the SHA1 and SHA256 banks */
620 if (!IN_SET(pcap->data.assignedPCR.pcrSelections[i].hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
621 continue;
07697bfe 622
59fafaee
LP
623 r = tpm2_bank_has24(pcap->data.assignedPCR.pcrSelections + i);
624 if (r < 0)
625 return r;
626 if (!r)
07697bfe 627 continue;
07697bfe 628
321a9d9e
LP
629 good = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
630 if (good < 0)
631 return good;
632
07697bfe 633 if (pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA256) {
321a9d9e
LP
634 supported_hash = TPM2_ALG_SHA256;
635 if (good) {
636 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
637 hash_with_valid_pcr = TPM2_ALG_SHA256;
638 break;
639 }
640 } else {
641 assert(pcap->data.assignedPCR.pcrSelections[i].hash == TPM2_ALG_SHA1);
642
643 if (supported_hash == 0)
644 supported_hash = TPM2_ALG_SHA1;
07697bfe 645
321a9d9e
LP
646 if (good && hash_with_valid_pcr == 0)
647 hash_with_valid_pcr = TPM2_ALG_SHA1;
648 }
07697bfe
LP
649 }
650
321a9d9e
LP
651 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
652 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
653 * SHA1.
654 *
655 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
656 * not initialized. */
657
658 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
659 assert(supported_hash == TPM2_ALG_SHA256);
660 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
661 *ret = TPM2_ALG_SHA256;
662 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
663 if (supported_hash == TPM2_ALG_SHA256)
664 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.");
665 else {
666 assert(supported_hash == TPM2_ALG_SHA1);
667 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.");
668 }
669
670 *ret = TPM2_ALG_SHA1;
671 } else if (supported_hash == TPM2_ALG_SHA256) {
672 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!");
673 *ret = TPM2_ALG_SHA256;
674 } else if (supported_hash == TPM2_ALG_SHA1) {
675 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!");
676 *ret = TPM2_ALG_SHA1;
677 } else
07697bfe
LP
678 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
679 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
680
07697bfe
LP
681 return 0;
682}
683
c5bf1f85 684int tpm2_get_good_pcr_banks(
23e9ccc2 685 Tpm2Context *c,
c5bf1f85
LP
686 uint32_t pcr_mask,
687 TPMI_ALG_HASH **ret) {
688
689 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
690 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *pcap = NULL;
691 size_t n_good_banks = 0, n_fallback_banks = 0;
692 TPMI_YES_NO more;
693 TSS2_RC rc;
694 int r;
695
696 assert(c);
697 assert(ret);
698
699 rc = sym_Esys_GetCapability(
23e9ccc2 700 c->esys_context,
c5bf1f85
LP
701 ESYS_TR_NONE,
702 ESYS_TR_NONE,
703 ESYS_TR_NONE,
704 TPM2_CAP_PCRS,
705 0,
706 1,
707 &more,
708 &pcap);
709 if (rc != TSS2_RC_SUCCESS)
710 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
711 "Failed to determine TPM2 PCR bank capabilities: %s", sym_Tss2_RC_Decode(rc));
712
713 assert(pcap->capability == TPM2_CAP_PCRS);
714
715 for (size_t i = 0; i < pcap->data.assignedPCR.count; i++) {
716
717 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
718 r = tpm2_bank_has24(pcap->data.assignedPCR.pcrSelections + i);
719 if (r < 0)
720 return r;
721 if (!r)
722 continue;
723
724 /* Let's now see if this bank has any of the selected PCRs actually initialized */
725 r = tpm2_pcr_mask_good(c, pcap->data.assignedPCR.pcrSelections[i].hash, pcr_mask);
726 if (r < 0)
727 return r;
728
729 if (n_good_banks + n_fallback_banks >= INT_MAX)
730 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
731
732 if (r) {
733 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
734 return log_oom();
735
736 good_banks[n_good_banks++] = pcap->data.assignedPCR.pcrSelections[i].hash;
737 } else {
738 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
739 return log_oom();
740
741 fallback_banks[n_fallback_banks++] = pcap->data.assignedPCR.pcrSelections[i].hash;
742 }
743 }
744
745 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
746 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
747 if (n_good_banks > 0) {
748 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
749 *ret = TAKE_PTR(good_banks);
750 return (int) n_good_banks;
751 }
752 if (n_fallback_banks > 0) {
753 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
754 *ret = TAKE_PTR(fallback_banks);
755 return (int) n_fallback_banks;
756 }
757
758 /* No suitable banks found. */
759 *ret = NULL;
760 return 0;
761}
762
e4481cc5 763int tpm2_get_good_pcr_banks_strv(
23e9ccc2 764 Tpm2Context *c,
e4481cc5
LP
765 uint32_t pcr_mask,
766 char ***ret) {
767
0d7009d3 768#if HAVE_OPENSSL
e4481cc5
LP
769 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
770 _cleanup_strv_free_ char **l = NULL;
771 int n_algs;
772
773 assert(c);
774 assert(ret);
775
776 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
777 if (n_algs < 0)
778 return n_algs;
779
780 for (int i = 0; i < n_algs; i++) {
781 _cleanup_free_ char *n = NULL;
782 const EVP_MD *implementation;
783 const char *salg;
784
7bfe0a48 785 salg = tpm2_hash_alg_to_string(algs[i]);
e4481cc5
LP
786 if (!salg)
787 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
788
789 implementation = EVP_get_digestbyname(salg);
790 if (!implementation)
791 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
792
793 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
794 if (!n)
795 return log_oom();
796
797 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
798
799 if (strv_consume(&l, TAKE_PTR(n)) < 0)
800 return log_oom();
801 }
802
803 *ret = TAKE_PTR(l);
804 return 0;
0d7009d3
DS
805#else /* HAVE_OPENSSL */
806 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
807#endif
e4481cc5
LP
808}
809
0e15c14f
WR
810static void hash_pin(const char *pin, size_t len, TPM2B_AUTH *auth) {
811 struct sha256_ctx hash;
812
813 assert(auth);
814 assert(pin);
692597c8 815
0e15c14f
WR
816 auth->size = SHA256_DIGEST_SIZE;
817
692597c8
LP
818 CLEANUP_ERASE(hash);
819
0e15c14f
WR
820 sha256_init_ctx(&hash);
821 sha256_process_bytes(pin, len, &hash);
822 sha256_finish_ctx(&hash, auth->buffer);
0e15c14f
WR
823}
824
da29de23 825static int tpm2_make_encryption_session(
23e9ccc2 826 Tpm2Context *c,
16e16b8c
DS
827 const Tpm2Handle *primary,
828 const Tpm2Handle *bind_key,
0e15c14f 829 const char *pin,
16e16b8c 830 Tpm2Handle **ret_session) {
da29de23
GG
831
832 static const TPMT_SYM_DEF symmetric = {
833 .algorithm = TPM2_ALG_AES,
4dde902e
LP
834 .keyBits.aes = 128,
835 .mode.aes = TPM2_ALG_CFB,
da29de23
GG
836 };
837 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
838 TPMA_SESSION_CONTINUESESSION;
da29de23 839 TSS2_RC rc;
16e16b8c 840 int r;
da29de23
GG
841
842 assert(c);
16e16b8c 843 assert(ret_session);
da29de23 844
0e15c14f
WR
845 /*
846 * if a pin is set for the seal object, use it to bind the session
847 * key to that object. This prevents active bus interposers from
848 * faking a TPM and seeing the unsealed value. An active interposer
849 * could fake a TPM, satisfying the encrypted session, and just
850 * forward everything to the *real* TPM.
851 */
852 if (pin) {
853 TPM2B_AUTH auth = {};
854
692597c8
LP
855 CLEANUP_ERASE(auth);
856
0e15c14f
WR
857 hash_pin(pin, strlen(pin), &auth);
858
16e16b8c 859 rc = sym_Esys_TR_SetAuth(c->esys_context, bind_key->esys_handle, &auth);
0e15c14f
WR
860 if (rc != TSS2_RC_SUCCESS)
861 return log_error_errno(
862 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
863 "Failed to load PIN in TPM: %s",
864 sym_Tss2_RC_Decode(rc));
865 }
866
da29de23
GG
867 log_debug("Starting HMAC encryption session.");
868
869 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
870 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
871 * recover the salt, which is then used for key derivation. */
16e16b8c
DS
872 _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
873 r = tpm2_handle_new(c, &session);
874 if (r < 0)
875 return r;
876
da29de23 877 rc = sym_Esys_StartAuthSession(
23e9ccc2 878 c->esys_context,
16e16b8c
DS
879 primary->esys_handle,
880 bind_key->esys_handle,
da29de23
GG
881 ESYS_TR_NONE,
882 ESYS_TR_NONE,
883 ESYS_TR_NONE,
884 NULL,
885 TPM2_SE_HMAC,
886 &symmetric,
887 TPM2_ALG_SHA256,
16e16b8c 888 &session->esys_handle);
da29de23
GG
889 if (rc != TSS2_RC_SUCCESS)
890 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
891 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
892
893 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
894 * always used for sessions), this provides confidentiality, integrity and replay protection for
895 * operations that use this session. */
16e16b8c 896 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
da29de23
GG
897 if (rc != TSS2_RC_SUCCESS)
898 return log_error_errno(
899 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
900 "Failed to configure TPM session: %s",
901 sym_Tss2_RC_Decode(rc));
902
16e16b8c 903 *ret_session = TAKE_PTR(session);
da29de23 904
da29de23
GG
905 return 0;
906}
907
395c1d9a 908#if HAVE_OPENSSL
d9b5841d
LP
909static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output) {
910#if OPENSSL_VERSION_MAJOR >= 3
911 _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL;
912#else
913 const BIGNUM *n = NULL, *e = NULL;
914 const RSA *rsa = NULL;
915#endif
916 int n_bytes, e_bytes;
917
918 assert(input);
919 assert(output);
920
921 /* Converts an OpenSSL public key to a structure that the TPM chip can process. */
922
923 if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA)
924 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key.");
925
926#if OPENSSL_VERSION_MAJOR >= 3
927 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_N, &n))
928 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
929#else
930 rsa = EVP_PKEY_get0_RSA(input);
931 if (!rsa)
932 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to extract RSA key from public key.");
933
934 n = RSA_get0_n(rsa);
935 if (!n)
936 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA modulus from public key.");
937#endif
938
939 n_bytes = BN_num_bytes(n);
940 assert_se(n_bytes > 0);
941 if ((size_t) n_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.unique.rsa.buffer))
942 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA modulus too large for TPM2 public key object.");
943
944#if OPENSSL_VERSION_MAJOR >= 3
945 if (!EVP_PKEY_get_bn_param(input, OSSL_PKEY_PARAM_RSA_E, &e))
946 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
947#else
948 e = RSA_get0_e(rsa);
949 if (!e)
950 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get RSA exponent from public key.");
951#endif
952
953 e_bytes = BN_num_bytes(e);
954 assert_se(e_bytes > 0);
955 if ((size_t) e_bytes > sizeof_field(TPM2B_PUBLIC, publicArea.parameters.rsaDetail.exponent))
956 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RSA exponent too large for TPM2 public key object.");
957
958 *output = (TPM2B_PUBLIC) {
959 .size = sizeof(TPMT_PUBLIC),
960 .publicArea = {
961 .type = TPM2_ALG_RSA,
962 .nameAlg = TPM2_ALG_SHA256,
963 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
964 .parameters.rsaDetail = {
965 .scheme = {
966 .scheme = TPM2_ALG_NULL,
967 .details.anySig.hashAlg = TPM2_ALG_NULL,
968 },
969 .symmetric = {
970 .algorithm = TPM2_ALG_NULL,
971 .mode.sym = TPM2_ALG_NULL,
972 },
973 .keyBits = n_bytes * 8,
974 /* .exponent will be filled in below. */
975 },
976 .unique = {
977 .rsa.size = n_bytes,
978 /* .rsa.buffer will be filled in below. */
979 },
980 },
981 };
982
983 if (BN_bn2bin(n, output->publicArea.unique.rsa.buffer) <= 0)
984 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA modulus.");
985
986 if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0)
987 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent.");
988
989 return 0;
990}
991
992static int find_signature(
993 JsonVariant *v,
994 uint16_t pcr_bank,
995 uint32_t pcr_mask,
996 EVP_PKEY *pk,
997 const void *policy,
998 size_t policy_size,
999 void *ret_signature,
1000 size_t *ret_signature_size) {
1001
1002 _cleanup_free_ void *fp = NULL;
1003 JsonVariant *b, *i;
1004 size_t fp_size;
1005 const char *k;
1006 int r;
1007
1008 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
1009 * public key, and policy digest. */
1010
1011 if (!json_variant_is_object(v))
1012 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
1013
7bfe0a48 1014 k = tpm2_hash_alg_to_string(pcr_bank);
d9b5841d
LP
1015 if (!k)
1016 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
1017
1018 /* First, find field by bank */
1019 b = json_variant_by_key(v, k);
1020 if (!b)
1021 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
1022
1023 if (!json_variant_is_array(b))
1024 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
1025
1026 /* Now iterate through all signatures known for this bank */
1027 JSON_VARIANT_ARRAY_FOREACH(i, b) {
1028 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
1029 JsonVariant *maskj, *fpj, *sigj, *polj;
1030 size_t fpj_size, polj_size;
1031 uint32_t parsed_mask;
1032
1033 if (!json_variant_is_object(i))
1034 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
1035
1036 /* Check if the PCR mask matches our expectations */
1037 maskj = json_variant_by_key(i, "pcrs");
1038 if (!maskj)
1039 continue;
1040
1041 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
1042 if (r < 0)
1043 return log_error_errno(r, "Failed to parse JSON PCR mask");
1044
1045 if (parsed_mask != pcr_mask)
1046 continue; /* Not for this PCR mask */
1047
1048 /* Then check if this is for the public key we operate with */
1049 fpj = json_variant_by_key(i, "pkfp");
1050 if (!fpj)
1051 continue;
1052
1053 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
1054 if (r < 0)
1055 return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
1056
1057 if (!fp) {
1058 r = pubkey_fingerprint(pk, EVP_sha256(), &fp, &fp_size);
1059 if (r < 0)
1060 return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
1061 }
1062
1063 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
1064 continue; /* Not for this public key */
1065
1066 /* Finally, check if this is for the PCR policy we expect this to be */
1067 polj = json_variant_by_key(i, "pol");
1068 if (!polj)
1069 continue;
1070
1071 r = json_variant_unhex(polj, &polj_data, &polj_size);
1072 if (r < 0)
1073 return log_error_errno(r, "Failed to decode policy hash JSON data: %m");
1074
1075 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
1076 continue;
1077
1078 /* This entry matches all our expectations, now return the signature included in it */
1079 sigj = json_variant_by_key(i, "sig");
1080 if (!sigj)
1081 continue;
1082
1083 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
1084 }
1085
1086 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
1087}
395c1d9a 1088#endif
d9b5841d
LP
1089
1090static int tpm2_make_policy_session(
23e9ccc2 1091 Tpm2Context *c,
16e16b8c
DS
1092 const Tpm2Handle *primary,
1093 const Tpm2Handle *parent_session,
73096907 1094 TPM2_SE session_type,
d9b5841d 1095 uint32_t hash_pcr_mask,
07697bfe 1096 uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
d9b5841d
LP
1097 const void *pubkey,
1098 size_t pubkey_size,
1099 uint32_t pubkey_pcr_mask,
1100 JsonVariant *signature_json,
2f5a892a 1101 bool use_pin,
16e16b8c 1102 Tpm2Handle **ret_session,
07697bfe
LP
1103 TPM2B_DIGEST **ret_policy_digest,
1104 TPMI_ALG_HASH *ret_pcr_bank) {
5e521624
LP
1105
1106 static const TPMT_SYM_DEF symmetric = {
1107 .algorithm = TPM2_ALG_AES,
821d94c4
LP
1108 .keyBits.aes = 128,
1109 .mode.aes = TPM2_ALG_CFB,
5e521624 1110 };
5e521624 1111 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
5e521624
LP
1112 TSS2_RC rc;
1113 int r;
1114
1115 assert(c);
d9b5841d
LP
1116 assert(pubkey || pubkey_size == 0);
1117 assert(pubkey_pcr_mask == 0 || pubkey_size > 0);
5e521624
LP
1118
1119 log_debug("Starting authentication session.");
1120
251d2ea2
LP
1121 /* So apparently some TPM implementations don't implement trial mode correctly. To avoid issues let's
1122 * avoid it when it is easy to. At the moment we only really need trial mode for the signed PCR
1123 * policies (since only then we need to shove PCR values into the policy that don't match current
1124 * state anyway), hence if we have none of those we don't need to bother. Hence, let's patch in
1125 * TPM2_SE_POLICY even if trial mode is requested unless a pubkey PCR mask is specified that is
1126 * non-zero, i.e. signed PCR policy is requested.
1127 *
1128 * One day we should switch to calculating policy hashes client side when trial mode is requested, to
1129 * avoid this mess. */
1130 if (session_type == TPM2_SE_TRIAL && pubkey_pcr_mask == 0)
1131 session_type = TPM2_SE_POLICY;
1132
d9b5841d
LP
1133 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
1134 /* We are told to configure a PCR policy of some form, let's determine/validate the PCR bank to use. */
d38466ba 1135
d9b5841d
LP
1136 if (pcr_bank != UINT16_MAX) {
1137 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
1138 if (r < 0)
1139 return r;
1140 if (r == 0)
1141 log_warning("Selected TPM2 PCRs are not initialized on this system, most likely due to a firmware issue. PCR policy is effectively not enforced. Proceeding anyway.");
1142 } else {
1143 /* No bank configured, pick automatically. Some TPM2 devices only can do SHA1. If we
1144 * detect that use that, but preferably use SHA256 */
1145 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
1146 if (r < 0)
1147 return r;
1148 }
1149 }
321a9d9e 1150
395c1d9a
YW
1151#if HAVE_OPENSSL
1152 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
d9b5841d 1153 if (pubkey_size > 0) {
dc176813
ZJS
1154 /* If a pubkey is specified, load it to validate it, even if the PCR mask for this is
1155 * actually zero, and we are thus not going to use it. */
d9b5841d
LP
1156 _cleanup_fclose_ FILE *f = fmemopen((void*) pubkey, pubkey_size, "r");
1157 if (!f)
1158 return log_oom();
321a9d9e 1159
d9b5841d
LP
1160 pk = PEM_read_PUBKEY(f, NULL, NULL, NULL);
1161 if (!pk)
1162 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
07697bfe 1163 }
395c1d9a 1164#endif
07697bfe 1165
16e16b8c
DS
1166 _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
1167 r = tpm2_handle_new(c, &session);
1168 if (r < 0)
1169 return r;
1170
5e521624 1171 rc = sym_Esys_StartAuthSession(
23e9ccc2 1172 c->esys_context,
16e16b8c 1173 primary->esys_handle,
5e521624 1174 ESYS_TR_NONE,
16e16b8c 1175 parent_session->esys_handle,
5e521624
LP
1176 ESYS_TR_NONE,
1177 ESYS_TR_NONE,
1178 NULL,
73096907 1179 session_type,
5e521624
LP
1180 &symmetric,
1181 TPM2_ALG_SHA256,
16e16b8c 1182 &session->esys_handle);
5e521624
LP
1183 if (rc != TSS2_RC_SUCCESS)
1184 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1185 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
1186
d9b5841d 1187 if (pubkey_pcr_mask != 0) {
395c1d9a 1188#if HAVE_OPENSSL
d9b5841d 1189 log_debug("Configuring public key based PCR policy.");
5e521624 1190
d9b5841d
LP
1191 /* First: load public key into the TPM */
1192 TPM2B_PUBLIC pubkey_tpm2;
1193 r = openssl_pubkey_to_tpm2_pubkey(pk, &pubkey_tpm2);
1194 if (r < 0)
16e16b8c
DS
1195 return r;
1196
1197 _cleanup_tpm2_handle_ Tpm2Handle *pubkey_handle = NULL;
1198 r = tpm2_handle_new(c, &pubkey_handle);
1199 if (r < 0)
1200 return r;
d9b5841d
LP
1201
1202 rc = sym_Esys_LoadExternal(
23e9ccc2 1203 c->esys_context,
d9b5841d
LP
1204 ESYS_TR_NONE,
1205 ESYS_TR_NONE,
1206 ESYS_TR_NONE,
1207 NULL,
1208 &pubkey_tpm2,
155c5129
VK
1209#if HAVE_TSS2_ESYS3
1210 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
1211 * hierarchy, older versions need TPM2_RH_* instead. */
1212 ESYS_TR_RH_OWNER,
1213#else
d9b5841d 1214 TPM2_RH_OWNER,
155c5129 1215#endif
16e16b8c
DS
1216 &pubkey_handle->esys_handle);
1217 if (rc != TSS2_RC_SUCCESS)
1218 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1219 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
d9b5841d
LP
1220
1221 /* Acquire the "name" of what we just loaded */
1222 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
1223 rc = sym_Esys_TR_GetName(
23e9ccc2 1224 c->esys_context,
16e16b8c 1225 pubkey_handle->esys_handle,
d9b5841d 1226 &pubkey_name);
16e16b8c
DS
1227 if (rc != TSS2_RC_SUCCESS)
1228 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1229 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
d9b5841d
LP
1230
1231 /* Put together the PCR policy we want to use */
1232 TPML_PCR_SELECTION pcr_selection;
1233 tpm2_pcr_mask_to_selection(pubkey_pcr_mask, pcr_bank, &pcr_selection);
1234 rc = sym_Esys_PolicyPCR(
23e9ccc2 1235 c->esys_context,
16e16b8c 1236 session->esys_handle,
d9b5841d
LP
1237 ESYS_TR_NONE,
1238 ESYS_TR_NONE,
1239 ESYS_TR_NONE,
1240 NULL,
1241 &pcr_selection);
16e16b8c
DS
1242 if (rc != TSS2_RC_SUCCESS)
1243 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1244 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
d9b5841d
LP
1245
1246 /* Get the policy hash of the PCR policy */
1247 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
1248 rc = sym_Esys_PolicyGetDigest(
23e9ccc2 1249 c->esys_context,
16e16b8c 1250 session->esys_handle,
d9b5841d
LP
1251 ESYS_TR_NONE,
1252 ESYS_TR_NONE,
1253 ESYS_TR_NONE,
1254 &approved_policy);
16e16b8c
DS
1255 if (rc != TSS2_RC_SUCCESS)
1256 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1257 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
d9b5841d
LP
1258
1259 /* When we are unlocking and have a signature, let's pass it to the TPM */
1260 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
1261 const TPMT_TK_VERIFIED *check_ticket;
1262 if (signature_json) {
1263 _cleanup_free_ void *signature_raw = NULL;
1264 size_t signature_size;
1265
1266 r = find_signature(
1267 signature_json,
1268 pcr_bank,
1269 pubkey_pcr_mask,
1270 pk,
1271 approved_policy->buffer,
1272 approved_policy->size,
1273 &signature_raw,
1274 &signature_size);
1275 if (r < 0)
16e16b8c 1276 return r;
d9b5841d
LP
1277
1278 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
af3d3873 1279 * hence we need to do the SHA256 part ourselves, first */
d9b5841d
LP
1280 TPM2B_DIGEST signature_hash = {
1281 .size = SHA256_DIGEST_SIZE,
1282 };
1283 assert(sizeof(signature_hash.buffer) >= SHA256_DIGEST_SIZE);
1284 sha256_direct(approved_policy->buffer, approved_policy->size, signature_hash.buffer);
1285
1286 TPMT_SIGNATURE policy_signature = {
1287 .sigAlg = TPM2_ALG_RSASSA,
1288 .signature.rsassa = {
1289 .hash = TPM2_ALG_SHA256,
1290 .sig.size = signature_size,
1291 },
1292 };
16e16b8c
DS
1293 if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer))
1294 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
d9b5841d
LP
1295 memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
1296
1297 rc = sym_Esys_VerifySignature(
23e9ccc2 1298 c->esys_context,
16e16b8c 1299 pubkey_handle->esys_handle,
d9b5841d
LP
1300 ESYS_TR_NONE,
1301 ESYS_TR_NONE,
1302 ESYS_TR_NONE,
1303 &signature_hash,
1304 &policy_signature,
1305 &check_ticket_buffer);
16e16b8c
DS
1306 if (rc != TSS2_RC_SUCCESS)
1307 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1308 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
d9b5841d
LP
1309
1310 check_ticket = check_ticket_buffer;
1311 } else {
1312 /* When enrolling, we pass a NULL ticket */
1313 static const TPMT_TK_VERIFIED check_ticket_null = {
1314 .tag = TPM2_ST_VERIFIED,
1315 .hierarchy = TPM2_RH_OWNER,
1316 };
1317
1318 check_ticket = &check_ticket_null;
1319 }
1320
1321 rc = sym_Esys_PolicyAuthorize(
23e9ccc2 1322 c->esys_context,
16e16b8c 1323 session->esys_handle,
d9b5841d
LP
1324 ESYS_TR_NONE,
1325 ESYS_TR_NONE,
1326 ESYS_TR_NONE,
1327 approved_policy,
1328 /* policyRef= */ &(const TPM2B_NONCE) {},
1329 pubkey_name,
1330 check_ticket);
16e16b8c
DS
1331 if (rc != TSS2_RC_SUCCESS)
1332 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1333 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
395c1d9a
YW
1334#else
1335 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
1336#endif
d9b5841d
LP
1337 }
1338
1339 if (hash_pcr_mask != 0) {
1340 log_debug("Configuring hash-based PCR policy.");
1341
1342 TPML_PCR_SELECTION pcr_selection;
1343 tpm2_pcr_mask_to_selection(hash_pcr_mask, pcr_bank, &pcr_selection);
1344 rc = sym_Esys_PolicyPCR(
23e9ccc2 1345 c->esys_context,
16e16b8c 1346 session->esys_handle,
d9b5841d
LP
1347 ESYS_TR_NONE,
1348 ESYS_TR_NONE,
1349 ESYS_TR_NONE,
1350 NULL,
1351 &pcr_selection);
16e16b8c
DS
1352 if (rc != TSS2_RC_SUCCESS)
1353 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1354 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
5e521624
LP
1355 }
1356
2f5a892a 1357 if (use_pin) {
d9b5841d
LP
1358 log_debug("Configuring PIN policy.");
1359
2f5a892a 1360 rc = sym_Esys_PolicyAuthValue(
23e9ccc2 1361 c->esys_context,
16e16b8c 1362 session->esys_handle,
2f5a892a
GG
1363 ESYS_TR_NONE,
1364 ESYS_TR_NONE,
1365 ESYS_TR_NONE);
16e16b8c
DS
1366 if (rc != TSS2_RC_SUCCESS)
1367 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1368 "Failed to add authValue policy to TPM: %s",
1369 sym_Tss2_RC_Decode(rc));
2f5a892a
GG
1370 }
1371
5e521624
LP
1372 if (DEBUG_LOGGING || ret_policy_digest) {
1373 log_debug("Acquiring policy digest.");
1374
1375 rc = sym_Esys_PolicyGetDigest(
23e9ccc2 1376 c->esys_context,
16e16b8c 1377 session->esys_handle,
5e521624
LP
1378 ESYS_TR_NONE,
1379 ESYS_TR_NONE,
1380 ESYS_TR_NONE,
1381 &policy_digest);
1382
16e16b8c
DS
1383 if (rc != TSS2_RC_SUCCESS)
1384 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1385 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
5e521624
LP
1386
1387 if (DEBUG_LOGGING) {
1388 _cleanup_free_ char *h = NULL;
1389
1390 h = hexmem(policy_digest->buffer, policy_digest->size);
16e16b8c
DS
1391 if (!h)
1392 return log_oom();
5e521624
LP
1393
1394 log_debug("Session policy digest: %s", h);
1395 }
1396 }
1397
16e16b8c
DS
1398 if (ret_session)
1399 *ret_session = TAKE_PTR(session);
5e521624
LP
1400
1401 if (ret_policy_digest)
1402 *ret_policy_digest = TAKE_PTR(policy_digest);
1403
07697bfe 1404 if (ret_pcr_bank)
d9b5841d 1405 *ret_pcr_bank = pcr_bank;
07697bfe 1406
16e16b8c 1407 return 0;
5e521624
LP
1408}
1409
d9b5841d
LP
1410int tpm2_seal(const char *device,
1411 uint32_t hash_pcr_mask,
1412 const void *pubkey,
1413 const size_t pubkey_size,
1414 uint32_t pubkey_pcr_mask,
1415 const char *pin,
1416 void **ret_secret,
1417 size_t *ret_secret_size,
1418 void **ret_blob,
1419 size_t *ret_blob_size,
1420 void **ret_pcr_hash,
1421 size_t *ret_pcr_hash_size,
1422 uint16_t *ret_pcr_bank,
1423 uint16_t *ret_primary_alg) {
5e521624 1424
5e521624
LP
1425 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1426 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
1427 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1428 static const TPML_PCR_SELECTION creation_pcr = {};
1429 _cleanup_(erase_and_freep) void *secret = NULL;
e8858f11 1430 _cleanup_free_ void *hash = NULL;
692597c8 1431 TPM2B_SENSITIVE_CREATE hmac_sensitive;
2b92a672 1432 TPMI_ALG_PUBLIC primary_alg;
5e521624 1433 TPM2B_PUBLIC hmac_template;
07697bfe 1434 TPMI_ALG_HASH pcr_bank;
5e521624
LP
1435 usec_t start;
1436 TSS2_RC rc;
1437 int r;
1438
d9b5841d
LP
1439 assert(pubkey || pubkey_size == 0);
1440
5e521624
LP
1441 assert(ret_secret);
1442 assert(ret_secret_size);
1443 assert(ret_blob);
1444 assert(ret_blob_size);
1445 assert(ret_pcr_hash);
1446 assert(ret_pcr_hash_size);
07697bfe 1447 assert(ret_pcr_bank);
5e521624 1448
d9b5841d
LP
1449 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
1450 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624
LP
1451
1452 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
1453 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
2b92a672
LP
1454 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
1455 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
1456 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
1457 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
1458 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
1459 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
1460 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
1461 * LUKS2 JSON header.
5e521624
LP
1462 *
1463 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
1464 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
1465 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
1466 * binding the unlocking to the TPM2 chip. */
1467
1468 start = now(CLOCK_MONOTONIC);
1469
692597c8
LP
1470 CLEANUP_ERASE(hmac_sensitive);
1471
68d084ce
DS
1472 _cleanup_tpm2_context_ Tpm2Context *c = NULL;
1473 r = tpm2_context_new(device, &c);
5e521624
LP
1474 if (r < 0)
1475 return r;
1476
16e16b8c 1477 _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
23e9ccc2 1478 r = tpm2_make_primary(c, &primary, 0, &primary_alg);
5e521624
LP
1479 if (r < 0)
1480 return r;
1481
0e15c14f 1482 /* we cannot use the bind key before its created */
16e16b8c
DS
1483 _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
1484 r = tpm2_make_encryption_session(c, primary, &TPM2_HANDLE_NONE, NULL, &session);
da29de23 1485 if (r < 0)
16e16b8c 1486 return r;
da29de23 1487
d9b5841d 1488 r = tpm2_make_policy_session(
23e9ccc2 1489 c,
73096907
LP
1490 primary,
1491 session,
1492 TPM2_SE_TRIAL,
d9b5841d 1493 hash_pcr_mask,
73096907 1494 /* pcr_bank= */ UINT16_MAX,
d9b5841d
LP
1495 pubkey, pubkey_size,
1496 pubkey_pcr_mask,
1497 /* signature_json= */ NULL,
73096907
LP
1498 !!pin,
1499 /* ret_session= */ NULL,
1500 &policy_digest,
1501 &pcr_bank);
5e521624 1502 if (r < 0)
16e16b8c 1503 return r;
5e521624
LP
1504
1505 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
1506 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
1507 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
1508 hmac_template = (TPM2B_PUBLIC) {
1509 .size = sizeof(TPMT_PUBLIC),
1510 .publicArea = {
1511 .type = TPM2_ALG_KEYEDHASH,
1512 .nameAlg = TPM2_ALG_SHA256,
1513 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
821d94c4 1514 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
1200777b 1515 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
5e521624
LP
1516 .authPolicy = *policy_digest,
1517 },
1518 };
1519
1520 hmac_sensitive = (TPM2B_SENSITIVE_CREATE) {
1521 .size = sizeof(hmac_sensitive.sensitive),
1522 .sensitive.data.size = 32,
1523 };
0e15c14f
WR
1524 if (pin)
1525 hash_pin(pin, strlen(pin), &hmac_sensitive.sensitive.userAuth);
1526
5e521624
LP
1527 assert(sizeof(hmac_sensitive.sensitive.data.buffer) >= hmac_sensitive.sensitive.data.size);
1528
23e9ccc2 1529 (void) tpm2_credit_random(c);
5e521624
LP
1530
1531 log_debug("Generating secret key data.");
1532
87cb1ab6 1533 r = crypto_random_bytes(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
16e16b8c
DS
1534 if (r < 0)
1535 return log_error_errno(r, "Failed to generate secret key: %m");
5e521624
LP
1536
1537 log_debug("Creating HMAC key.");
1538
1539 rc = sym_Esys_Create(
68d084ce 1540 c->esys_context,
16e16b8c
DS
1541 primary->esys_handle,
1542 session->esys_handle, /* use HMAC session to enable parameter encryption */
5e521624
LP
1543 ESYS_TR_NONE,
1544 ESYS_TR_NONE,
1545 &hmac_sensitive,
1546 &hmac_template,
1547 NULL,
1548 &creation_pcr,
1549 &private,
1550 &public,
1551 NULL,
1552 NULL,
1553 NULL);
16e16b8c
DS
1554 if (rc != TSS2_RC_SUCCESS)
1555 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1556 "Failed to generate HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
5e521624
LP
1557
1558 secret = memdup(hmac_sensitive.sensitive.data.buffer, hmac_sensitive.sensitive.data.size);
16e16b8c
DS
1559 if (!secret)
1560 return log_oom();
5e521624
LP
1561
1562 log_debug("Marshalling private and public part of HMAC key.");
1563
e8858f11
DS
1564 _cleanup_free_ void *blob = NULL;
1565 size_t max_size = sizeof(*private) + sizeof(*public), blob_size = 0;
5e521624 1566
e8858f11
DS
1567 blob = malloc0(max_size);
1568 if (!blob)
1569 return log_oom();
5e521624 1570
e8858f11
DS
1571 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
1572 if (rc != TSS2_RC_SUCCESS)
1573 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1574 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
5e521624 1575
e8858f11
DS
1576 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
1577 if (rc != TSS2_RC_SUCCESS)
1578 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1579 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
5e521624
LP
1580
1581 hash = memdup(policy_digest->buffer, policy_digest->size);
1582 if (!hash)
1583 return log_oom();
1584
5291f26d
ZJS
1585 if (DEBUG_LOGGING)
1586 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624
LP
1587
1588 *ret_secret = TAKE_PTR(secret);
1589 *ret_secret_size = hmac_sensitive.sensitive.data.size;
1590 *ret_blob = TAKE_PTR(blob);
1591 *ret_blob_size = blob_size;
1592 *ret_pcr_hash = TAKE_PTR(hash);
1593 *ret_pcr_hash_size = policy_digest->size;
07697bfe 1594 *ret_pcr_bank = pcr_bank;
2b92a672 1595 *ret_primary_alg = primary_alg;
5e521624 1596
16e16b8c 1597 return 0;
5e521624
LP
1598}
1599
0254e4d6
AAF
1600#define RETRY_UNSEAL_MAX 30u
1601
d9b5841d
LP
1602int tpm2_unseal(const char *device,
1603 uint32_t hash_pcr_mask,
07697bfe 1604 uint16_t pcr_bank,
d9b5841d
LP
1605 const void *pubkey,
1606 size_t pubkey_size,
1607 uint32_t pubkey_pcr_mask,
1608 JsonVariant *signature,
1609 const char *pin,
2b92a672 1610 uint16_t primary_alg,
5e521624
LP
1611 const void *blob,
1612 size_t blob_size,
1613 const void *known_policy_hash,
1614 size_t known_policy_hash_size,
1615 void **ret_secret,
1616 size_t *ret_secret_size) {
1617
5e521624
LP
1618 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
1619 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1620 _cleanup_(erase_and_freep) char *secret = NULL;
1621 TPM2B_PRIVATE private = {};
1622 TPM2B_PUBLIC public = {};
1623 size_t offset = 0;
1624 TSS2_RC rc;
1625 usec_t start;
1626 int r;
1627
1628 assert(blob);
1629 assert(blob_size > 0);
1630 assert(known_policy_hash_size == 0 || known_policy_hash);
d9b5841d 1631 assert(pubkey_size == 0 || pubkey);
5e521624
LP
1632 assert(ret_secret);
1633 assert(ret_secret_size);
1634
d9b5841d
LP
1635 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
1636 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624 1637
1b30720c
LP
1638 r = dlopen_tpm2();
1639 if (r < 0)
1640 return log_error_errno(r, "TPM2 support is not installed.");
1641
5e521624 1642 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
dc176813
ZJS
1643 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
1644 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
1645 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
1646 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
1647 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5e521624
LP
1648 * and use it to unlock the LUKS2 volume. */
1649
1650 start = now(CLOCK_MONOTONIC);
1651
1652 log_debug("Unmarshalling private part of HMAC key.");
1653
1654 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
1655 if (rc != TSS2_RC_SUCCESS)
1656 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1657 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
1658
1659 log_debug("Unmarshalling public part of HMAC key.");
1660
1661 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
1662 if (rc != TSS2_RC_SUCCESS)
1663 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1664 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
1665
68d084ce
DS
1666 _cleanup_tpm2_context_ Tpm2Context *c = NULL;
1667 r = tpm2_context_new(device, &c);
5e521624
LP
1668 if (r < 0)
1669 return r;
1670
16e16b8c 1671 _cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
23e9ccc2 1672 r = tpm2_make_primary(c, &primary, primary_alg, NULL);
da29de23
GG
1673 if (r < 0)
1674 return r;
1675
5e521624
LP
1676 log_debug("Loading HMAC key into TPM.");
1677
0e15c14f
WR
1678 /*
1679 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
1680 * gives you back a different key, the session initiation will fail if a pin
1681 * is provided. If an attacker gives back a bad key, we already lost since
1682 * primary key is not verified and they could attack there as well.
1683 */
16e16b8c
DS
1684 _cleanup_tpm2_handle_ Tpm2Handle *hmac_key = NULL;
1685 r = tpm2_handle_new(c, &hmac_key);
1686 if (r < 0)
1687 return r;
1688
5e521624 1689 rc = sym_Esys_Load(
68d084ce 1690 c->esys_context,
16e16b8c 1691 primary->esys_handle,
0e15c14f 1692 ESYS_TR_PASSWORD,
5e521624
LP
1693 ESYS_TR_NONE,
1694 ESYS_TR_NONE,
1695 &private,
1696 &public,
16e16b8c 1697 &hmac_key->esys_handle);
5e521624 1698 if (rc != TSS2_RC_SUCCESS) {
2f5a892a
GG
1699 /* If we're in dictionary attack lockout mode, we should see a lockout error here, which we
1700 * need to translate for the caller. */
1701 if (rc == TPM2_RC_LOCKOUT)
16e16b8c 1702 return log_error_errno(
2f5a892a
GG
1703 SYNTHETIC_ERRNO(ENOLCK),
1704 "TPM2 device is in dictionary attack lockout mode.");
1705 else
16e16b8c 1706 return log_error_errno(
2f5a892a
GG
1707 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1708 "Failed to load HMAC key in TPM: %s",
1709 sym_Tss2_RC_Decode(rc));
5e521624
LP
1710 }
1711
16e16b8c 1712 _cleanup_tpm2_handle_ Tpm2Handle *hmac_session = NULL;
23e9ccc2 1713 r = tpm2_make_encryption_session(c, primary, hmac_key, pin, &hmac_session);
0e15c14f 1714 if (r < 0)
16e16b8c 1715 return r;
2f5a892a 1716
0254e4d6 1717 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
16e16b8c 1718 _cleanup_tpm2_handle_ Tpm2Handle *policy_session = NULL;
0254e4d6 1719 r = tpm2_make_policy_session(
23e9ccc2 1720 c,
0254e4d6
AAF
1721 primary,
1722 hmac_session,
1723 TPM2_SE_POLICY,
1724 hash_pcr_mask,
1725 pcr_bank,
1726 pubkey, pubkey_size,
1727 pubkey_pcr_mask,
1728 signature,
1729 !!pin,
16e16b8c 1730 &policy_session,
0254e4d6
AAF
1731 &policy_digest,
1732 /* ret_pcr_bank= */ NULL);
1733 if (r < 0)
16e16b8c 1734 return r;
2f5a892a 1735
0254e4d6
AAF
1736 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
1737 * wait until the TPM2 tells us to go away. */
1738 if (known_policy_hash_size > 0 &&
1739 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
1740 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
1741 "Current policy digest does not match stored policy digest, cancelling "
1742 "TPM2 authentication attempt.");
2f5a892a 1743
0254e4d6 1744 log_debug("Unsealing HMAC key.");
5e521624 1745
0254e4d6 1746 rc = sym_Esys_Unseal(
68d084ce 1747 c->esys_context,
16e16b8c
DS
1748 hmac_key->esys_handle,
1749 policy_session->esys_handle,
1750 hmac_session->esys_handle, /* use HMAC session to enable parameter encryption */
0254e4d6
AAF
1751 ESYS_TR_NONE,
1752 &unsealed);
16e16b8c
DS
1753 if (rc == TSS2_RC_SUCCESS)
1754 break;
1755 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
1756 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1757 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
1758 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5e521624
LP
1759 }
1760
1761 secret = memdup(unsealed->buffer, unsealed->size);
1762 explicit_bzero_safe(unsealed->buffer, unsealed->size);
16e16b8c
DS
1763 if (!secret)
1764 return log_oom();
5e521624 1765
5291f26d
ZJS
1766 if (DEBUG_LOGGING)
1767 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624
LP
1768
1769 *ret_secret = TAKE_PTR(secret);
1770 *ret_secret_size = unsealed->size;
1771
16e16b8c 1772 return 0;
5e521624
LP
1773}
1774
1775#endif
1776
1777int tpm2_list_devices(void) {
1778#if HAVE_TPM2
1779 _cleanup_(table_unrefp) Table *t = NULL;
1780 _cleanup_(closedirp) DIR *d = NULL;
1781 int r;
1782
1783 r = dlopen_tpm2();
1784 if (r < 0)
1785 return log_error_errno(r, "TPM2 support is not installed.");
1786
1787 t = table_new("path", "device", "driver");
1788 if (!t)
1789 return log_oom();
1790
1791 d = opendir("/sys/class/tpmrm");
1792 if (!d) {
1793 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
1794 if (errno != ENOENT)
1795 return -errno;
1796 } else {
1797 for (;;) {
1798 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
1799 struct dirent *de;
1800
1801 de = readdir_no_dot(d);
1802 if (!de)
1803 break;
1804
1805 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
1806 if (!device_path)
1807 return log_oom();
1808
1809 r = readlink_malloc(device_path, &device);
1810 if (r < 0)
1811 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
1812 else {
1813 driver_path = path_join(device_path, "driver");
1814 if (!driver_path)
1815 return log_oom();
1816
1817 r = readlink_malloc(driver_path, &driver);
1818 if (r < 0)
1819 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
1820 }
1821
1822 node = path_join("/dev", de->d_name);
1823 if (!node)
1824 return log_oom();
1825
1826 r = table_add_many(
1827 t,
1828 TABLE_PATH, node,
1829 TABLE_STRING, device ? last_path_component(device) : NULL,
1830 TABLE_STRING, driver ? last_path_component(driver) : NULL);
1831 if (r < 0)
1832 return table_log_add_error(r);
1833 }
1834 }
1835
1836 if (table_get_rows(t) <= 1) {
1837 log_info("No suitable TPM2 devices found.");
1838 return 0;
1839 }
1840
1841 r = table_print(t, stdout);
1842 if (r < 0)
1843 return log_error_errno(r, "Failed to show device table: %m");
1844
1845 return 0;
1846#else
1847 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1848 "TPM2 not supported on this build.");
1849#endif
1850}
1851
1852int tpm2_find_device_auto(
1853 int log_level, /* log level when no device is found */
1854 char **ret) {
1855#if HAVE_TPM2
1856 _cleanup_(closedirp) DIR *d = NULL;
1857 int r;
1858
1859 r = dlopen_tpm2();
1860 if (r < 0)
1861 return log_error_errno(r, "TPM2 support is not installed.");
1862
1863 d = opendir("/sys/class/tpmrm");
1864 if (!d) {
1865 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
1866 "Failed to open /sys/class/tpmrm: %m");
1867 if (errno != ENOENT)
1868 return -errno;
1869 } else {
1870 _cleanup_free_ char *node = NULL;
1871
1872 for (;;) {
1873 struct dirent *de;
1874
1875 de = readdir_no_dot(d);
1876 if (!de)
1877 break;
1878
1879 if (node)
1880 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
1881 "More than one TPM2 (tpmrm) device found.");
1882
1883 node = path_join("/dev", de->d_name);
1884 if (!node)
1885 return log_oom();
1886 }
1887
1888 if (node) {
1889 *ret = TAKE_PTR(node);
1890 return 0;
1891 }
1892 }
1893
1894 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
1895#else
1896 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1897 "TPM2 not supported on this build.");
1898#endif
1899}
1900
15c591d1
LP
1901#if HAVE_TPM2
1902int tpm2_extend_bytes(
23e9ccc2 1903 Tpm2Context *c,
15c591d1
LP
1904 char **banks,
1905 unsigned pcr_index,
1906 const void *data,
9885c874
LP
1907 size_t data_size,
1908 const void *secret,
1909 size_t secret_size) {
15c591d1
LP
1910
1911#if HAVE_OPENSSL
1912 TPML_DIGEST_VALUES values = {};
1913 TSS2_RC rc;
1914
1915 assert(c);
9885c874
LP
1916 assert(data || data_size == 0);
1917 assert(secret || secret_size == 0);
1918
1919 if (data_size == SIZE_MAX)
1920 data_size = strlen(data);
1921 if (secret_size == SIZE_MAX)
1922 secret_size = strlen(secret);
15c591d1
LP
1923
1924 if (pcr_index >= TPM2_PCRS_MAX)
1925 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
1926
1927 if (strv_isempty(banks))
1928 return 0;
1929
1930 STRV_FOREACH(bank, banks) {
1931 const EVP_MD *implementation;
1932 int id;
1933
1934 assert_se(implementation = EVP_get_digestbyname(*bank));
1935
1936 if (values.count >= ELEMENTSOF(values.digests))
1937 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
1938
1939 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
1940 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
1941
7bfe0a48 1942 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
15c591d1
LP
1943 if (id < 0)
1944 return log_error_errno(id, "Can't map hash name to TPM2.");
1945
1946 values.digests[values.count].hashAlg = id;
1947
9885c874
LP
1948 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
1949 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
1950 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
1951 * secret for other purposes, maybe because it needs a shorter secret derived from it for
1952 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
1953 * private non-secret string instead. */
1954 if (secret_size > 0) {
1955 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
1956 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
1957 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
1958 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
15c591d1
LP
1959
1960 values.count++;
1961 }
1962
1963 rc = sym_Esys_PCR_Extend(
23e9ccc2 1964 c->esys_context,
15c591d1
LP
1965 ESYS_TR_PCR0 + pcr_index,
1966 ESYS_TR_PASSWORD,
1967 ESYS_TR_NONE,
1968 ESYS_TR_NONE,
1969 &values);
1970 if (rc != TSS2_RC_SUCCESS)
1971 return log_error_errno(
1972 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1973 "Failed to measure into PCR %u: %s",
1974 pcr_index,
1975 sym_Tss2_RC_Decode(rc));
1976
1977 return 0;
0d7009d3
DS
1978#else /* HAVE_OPENSSL */
1979 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
15c591d1
LP
1980#endif
1981}
1982#endif
1983
5e521624 1984int tpm2_parse_pcrs(const char *s, uint32_t *ret) {
99534007 1985 const char *p = ASSERT_PTR(s);
5e521624
LP
1986 uint32_t mask = 0;
1987 int r;
1988
d57f6340
LP
1989 if (isempty(s)) {
1990 *ret = 0;
1991 return 0;
1992 }
1993
a1788a69
LP
1994 /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
1995 * and most other tools expect comma separated PCR specifications. We also support "+" since in
1996 * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
1997 * avoid escaping. */
5e521624
LP
1998
1999 for (;;) {
2000 _cleanup_free_ char *pcr = NULL;
2001 unsigned n;
2002
a1788a69 2003 r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
5e521624
LP
2004 if (r == 0)
2005 break;
2006 if (r < 0)
2007 return log_error_errno(r, "Failed to parse PCR list: %s", s);
2008
2009 r = safe_atou(pcr, &n);
2010 if (r < 0)
2011 return log_error_errno(r, "Failed to parse PCR number: %s", pcr);
2012 if (n >= TPM2_PCRS_MAX)
2013 return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
2014 "PCR number out of range (valid range 0…23): %u", n);
2015
2016 mask |= UINT32_C(1) << n;
2017 }
2018
2019 *ret = mask;
2020 return 0;
2021}
2022
4436081e
LP
2023int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
2024 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
2025 JsonVariant* pcr_array[TPM2_PCRS_MAX];
2026 unsigned n_pcrs = 0;
2027 int r;
2028
2029 for (size_t i = 0; i < ELEMENTSOF(pcr_array); i++) {
2030 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
2031 continue;
2032
2033 r = json_variant_new_integer(pcr_array + n_pcrs, i);
2034 if (r < 0)
2035 goto finish;
2036
2037 n_pcrs++;
2038 }
2039
2040 r = json_variant_new_array(&a, pcr_array, n_pcrs);
2041 if (r < 0)
2042 goto finish;
2043
2044 if (ret)
2045 *ret = TAKE_PTR(a);
2046 r = 0;
2047
2048finish:
2049 json_variant_unref_many(pcr_array, n_pcrs);
2050 return r;
2051}
8de8ec88
LP
2052
2053int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
2054 JsonVariant *e;
2055 uint32_t mask = 0;
2056
2057 if (!json_variant_is_array(v))
2058 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
2059
2060 JSON_VARIANT_ARRAY_FOREACH(e, v) {
2061 uint64_t u;
2062
2063 if (!json_variant_is_unsigned(e))
2064 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
2065
2066 u = json_variant_unsigned(e);
2067 if (u >= TPM2_PCRS_MAX)
2068 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
2069
2070 mask |= UINT32_C(1) << u;
2071 }
2072
2073 if (ret)
2074 *ret = mask;
2075
2076 return 0;
2077}
4436081e 2078
5e521624
LP
2079int tpm2_make_luks2_json(
2080 int keyslot,
f0f4fcae 2081 uint32_t hash_pcr_mask,
07697bfe 2082 uint16_t pcr_bank,
f0f4fcae
LP
2083 const void *pubkey,
2084 size_t pubkey_size,
2085 uint32_t pubkey_pcr_mask,
2b92a672 2086 uint16_t primary_alg,
5e521624
LP
2087 const void *blob,
2088 size_t blob_size,
2089 const void *policy_hash,
2090 size_t policy_hash_size,
aae6eb96
WR
2091 const void *salt,
2092 size_t salt_size,
6c7a1681 2093 TPM2Flags flags,
5e521624
LP
2094 JsonVariant **ret) {
2095
f0f4fcae 2096 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
5e521624 2097 _cleanup_free_ char *keyslot_as_string = NULL;
5e521624
LP
2098 int r;
2099
2100 assert(blob || blob_size == 0);
2101 assert(policy_hash || policy_hash_size == 0);
f0f4fcae 2102 assert(pubkey || pubkey_size == 0);
5e521624
LP
2103
2104 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
2105 return -ENOMEM;
2106
f0f4fcae 2107 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
5e521624 2108 if (r < 0)
4436081e 2109 return r;
5e521624 2110
f0f4fcae
LP
2111 if (pubkey_pcr_mask != 0) {
2112 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
2113 if (r < 0)
2114 return r;
2115 }
2116
2117 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
2118 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
2119 * object should use "_" rather than "-" in field names. */
2120
5e521624
LP
2121 r = json_build(&v,
2122 JSON_BUILD_OBJECT(
0cdf6b14 2123 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
5e521624
LP
2124 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
2125 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
f0f4fcae 2126 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7bfe0a48
DS
2127 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
2128 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 2129 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
f0f4fcae
LP
2130 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
2131 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
aae6eb96
WR
2132 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
2133 JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size))));
5e521624
LP
2134 if (r < 0)
2135 return r;
2136
2137 if (ret)
2138 *ret = TAKE_PTR(v);
2139
2140 return keyslot;
2141}
07697bfe 2142
fdf6c27c
LP
2143int tpm2_parse_luks2_json(
2144 JsonVariant *v,
2145 int *ret_keyslot,
2146 uint32_t *ret_hash_pcr_mask,
2147 uint16_t *ret_pcr_bank,
2148 void **ret_pubkey,
2149 size_t *ret_pubkey_size,
2150 uint32_t *ret_pubkey_pcr_mask,
2151 uint16_t *ret_primary_alg,
2152 void **ret_blob,
2153 size_t *ret_blob_size,
2154 void **ret_policy_hash,
2155 size_t *ret_policy_hash_size,
aae6eb96
WR
2156 void **ret_salt,
2157 size_t *ret_salt_size,
fdf6c27c
LP
2158 TPM2Flags *ret_flags) {
2159
aae6eb96
WR
2160 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL;
2161 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0;
fdf6c27c
LP
2162 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
2163 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
2164 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
2165 int r, keyslot = -1;
2166 TPM2Flags flags = 0;
2167 JsonVariant *w;
2168
2169 assert(v);
2170
2171 if (ret_keyslot) {
2172 keyslot = cryptsetup_get_keyslot_from_token(v);
2173 if (keyslot < 0) {
2174 /* Return a recognizable error when parsing this field, so that callers can handle parsing
2175 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
2176 * spec */
2177 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
2178 return -EUCLEAN;
2179 }
2180 }
2181
2182 w = json_variant_by_key(v, "tpm2-pcrs");
2183 if (!w)
2184 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
2185
2186 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
2187 if (r < 0)
2188 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
2189
2190 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
2191 * to SHA256. */
2192 w = json_variant_by_key(v, "tpm2-pcr-bank");
2193 if (w) {
2194 /* The PCR bank field is optional */
2195
2196 if (!json_variant_is_string(w))
2197 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
2198
7bfe0a48 2199 r = tpm2_hash_alg_from_string(json_variant_string(w));
fdf6c27c
LP
2200 if (r < 0)
2201 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
2202
2203 pcr_bank = r;
2204 }
2205
2206 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
2207 * the algorithm was hardcoded to ECC. */
2208 w = json_variant_by_key(v, "tpm2-primary-alg");
2209 if (w) {
2210 /* The primary key algorithm is optional */
2211
2212 if (!json_variant_is_string(w))
2213 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
2214
7bfe0a48 2215 r = tpm2_asym_alg_from_string(json_variant_string(w));
fdf6c27c 2216 if (r < 0)
7bfe0a48 2217 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
fdf6c27c
LP
2218
2219 primary_alg = r;
2220 }
2221
2222 w = json_variant_by_key(v, "tpm2-blob");
2223 if (!w)
2224 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
2225
2226 r = json_variant_unbase64(w, &blob, &blob_size);
2227 if (r < 0)
2228 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
2229
2230 w = json_variant_by_key(v, "tpm2-policy-hash");
2231 if (!w)
2232 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
2233
2234 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
2235 if (r < 0)
2236 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
2237
2238 w = json_variant_by_key(v, "tpm2-pin");
2239 if (w) {
2240 if (!json_variant_is_boolean(w))
2241 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
2242
2243 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
2244 }
2245
aae6eb96
WR
2246 w = json_variant_by_key(v, "tpm2_salt");
2247 if (w) {
2248 r = json_variant_unbase64(w, &salt, &salt_size);
2249 if (r < 0)
2250 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
2251 }
2252
fdf6c27c
LP
2253 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
2254 if (w) {
2255 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
2256 if (r < 0)
2257 return r;
2258 }
2259
2260 w = json_variant_by_key(v, "tpm2_pubkey");
2261 if (w) {
2262 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
2263 if (r < 0)
2264 return log_debug_errno(r, "Failed to decode PCR public key.");
2265 } else if (pubkey_pcr_mask != 0)
2266 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
2267
2268 if (ret_keyslot)
2269 *ret_keyslot = keyslot;
2270 if (ret_hash_pcr_mask)
2271 *ret_hash_pcr_mask = hash_pcr_mask;
2272 if (ret_pcr_bank)
2273 *ret_pcr_bank = pcr_bank;
2274 if (ret_pubkey)
2275 *ret_pubkey = TAKE_PTR(pubkey);
2276 if (ret_pubkey_size)
2277 *ret_pubkey_size = pubkey_size;
2278 if (ret_pubkey_pcr_mask)
2279 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
2280 if (ret_primary_alg)
2281 *ret_primary_alg = primary_alg;
2282 if (ret_blob)
2283 *ret_blob = TAKE_PTR(blob);
2284 if (ret_blob_size)
2285 *ret_blob_size = blob_size;
2286 if (ret_policy_hash)
2287 *ret_policy_hash = TAKE_PTR(policy_hash);
2288 if (ret_policy_hash_size)
2289 *ret_policy_hash_size = policy_hash_size;
aae6eb96
WR
2290 if (ret_salt)
2291 *ret_salt = TAKE_PTR(salt);
2292 if (ret_salt_size)
2293 *ret_salt_size = salt_size;
fdf6c27c
LP
2294 if (ret_flags)
2295 *ret_flags = flags;
2296
2297 return 0;
2298}
2299
7bfe0a48
DS
2300const char *tpm2_hash_alg_to_string(uint16_t alg) {
2301 if (alg == TPM2_ALG_SHA1)
07697bfe 2302 return "sha1";
7bfe0a48 2303 if (alg == TPM2_ALG_SHA256)
98193c39 2304 return "sha256";
7bfe0a48 2305 if (alg == TPM2_ALG_SHA384)
98193c39 2306 return "sha384";
7bfe0a48 2307 if (alg == TPM2_ALG_SHA512)
98193c39 2308 return "sha512";
07697bfe
LP
2309 return NULL;
2310}
2311
7bfe0a48
DS
2312int tpm2_hash_alg_from_string(const char *alg) {
2313 if (strcaseeq_ptr(alg, "sha1"))
07697bfe 2314 return TPM2_ALG_SHA1;
7bfe0a48 2315 if (strcaseeq_ptr(alg, "sha256"))
98193c39 2316 return TPM2_ALG_SHA256;
7bfe0a48 2317 if (strcaseeq_ptr(alg, "sha384"))
98193c39 2318 return TPM2_ALG_SHA384;
7bfe0a48 2319 if (strcaseeq_ptr(alg, "sha512"))
98193c39 2320 return TPM2_ALG_SHA512;
07697bfe
LP
2321 return -EINVAL;
2322}
2b92a672 2323
7bfe0a48 2324const char *tpm2_asym_alg_to_string(uint16_t alg) {
2b92a672
LP
2325 if (alg == TPM2_ALG_ECC)
2326 return "ecc";
2327 if (alg == TPM2_ALG_RSA)
2328 return "rsa";
2329 return NULL;
2330}
2331
7bfe0a48 2332int tpm2_asym_alg_from_string(const char *alg) {
f92ebc86 2333 if (strcaseeq_ptr(alg, "ecc"))
2b92a672 2334 return TPM2_ALG_ECC;
f92ebc86 2335 if (strcaseeq_ptr(alg, "rsa"))
2b92a672
LP
2336 return TPM2_ALG_RSA;
2337 return -EINVAL;
2338}
ba578556
LP
2339
2340Tpm2Support tpm2_support(void) {
2341 Tpm2Support support = TPM2_SUPPORT_NONE;
2342 int r;
2343
44d5dd65
LP
2344 if (detect_container() <= 0) {
2345 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
2346 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
2347 * let's assume containers never have a TPM, at least for now. */
2348
db55bbf2 2349 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
44d5dd65
LP
2350 if (r < 0) {
2351 if (r != -ENOENT)
2352 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
2353 } else if (r == 0) /* populated! */
300bba79
DDM
2354 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
2355 else
2356 /* If the directory exists but is empty, we know the subsystem is enabled but no
2357 * driver has been loaded yet. */
2358 support |= TPM2_SUPPORT_SUBSYSTEM;
44d5dd65 2359 }
ba578556
LP
2360
2361 if (efi_has_tpm2())
2362 support |= TPM2_SUPPORT_FIRMWARE;
2363
2364#if HAVE_TPM2
2365 support |= TPM2_SUPPORT_SYSTEM;
2366#endif
2367
2368 return support;
2369}
222a951f
LP
2370
2371int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask) {
2372 uint32_t m;
2373 int r;
2374
2375 assert(mask);
2376
2377 /* For use in getopt_long() command line parsers: merges masks specified on the command line */
2378
2379 if (isempty(arg)) {
2380 *mask = 0;
2381 return 0;
2382 }
2383
2384 r = tpm2_parse_pcrs(arg, &m);
2385 if (r < 0)
2386 return r;
2387
2388 if (*mask == UINT32_MAX)
2389 *mask = m;
2390 else
2391 *mask |= m;
2392
2393 return 0;
2394}
6a0779cb
LP
2395
2396int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
2397 _cleanup_free_ char *discovered_path = NULL;
2398 _cleanup_fclose_ FILE *f = NULL;
2399 int r;
2400
2401 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
2402 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
2403
2404 if (!path)
2405 path = "tpm2-pcr-signature.json";
2406
2407 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
2408 if (r < 0)
2409 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
2410
2411 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
2412 if (r < 0)
2413 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
2414
2415 return 0;
2416}
2417
2418int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
2419 _cleanup_free_ char *discovered_path = NULL;
2420 _cleanup_fclose_ FILE *f = NULL;
2421 int r;
2422
2423 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
2424 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
2425
2426 if (!path)
2427 path = "tpm2-pcr-public-key.pem";
2428
2429 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
2430 if (r < 0)
2431 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
2432
2433 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
2434 if (r < 0)
2435 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
2436
2437 return 0;
2438}
4d5cc0d4
LP
2439
2440int pcr_mask_to_string(uint32_t mask, char **ret) {
2441 _cleanup_free_ char *buf = NULL;
2442 int r;
2443
2444 assert(ret);
2445
2446 for (unsigned i = 0; i < TPM2_PCRS_MAX; i++) {
2447 if (!(mask & (UINT32_C(1) << i)))
2448 continue;
2449
2450 r = strextendf_with_separator(&buf, "+", "%u", i);
2451 if (r < 0)
2452 return r;
2453 }
2454
2455 *ret = TAKE_PTR(buf);
2456 return 0;
2457}
aae6eb96
WR
2458
2459#define PBKDF2_HMAC_SHA256_ITERATIONS 10000
2460
2461/*
2462 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
2463 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
2464 * I found the wikipedia entry relevant and it contains links to
2465 * relevant RFCs:
2466 * - https://en.wikipedia.org/wiki/PBKDF2
2467 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
2468 */
2469int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
2470 size_t passlen,
2471 const void *salt,
2472 size_t saltlen,
2473 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
2474
2475 uint8_t _cleanup_(erase_and_freep) *buffer = NULL;
2476 uint8_t u[SHA256_DIGEST_SIZE];
2477
2478 /* To keep this simple, since derived KeyLen (dkLen in docs)
2479 * Is the same as the hash output, we don't need multiple
2480 * blocks. Part of the algorithm is to add the block count
2481 * in, but this can be hardcoded to 1.
2482 */
2483 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
2484
504d0acf 2485 assert (salt);
aae6eb96
WR
2486 assert (saltlen > 0);
2487 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
2488 assert (passlen > 0);
2489
2490 /*
2491 * Build a buffer of salt + block_cnt and hmac_sha256 it we
2492 * do this as we don't have a context builder for HMAC_SHA256.
2493 */
2494 buffer = malloc(saltlen + sizeof(block_cnt));
2495 if (!buffer)
2496 return -ENOMEM;
2497
2498 memcpy(buffer, salt, saltlen);
2499 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
2500
2501 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
2502
2503 /* dk needs to be an unmodified u as u gets modified in the loop */
2504 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
2505 uint8_t *dk = ret_key;
2506
2507 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
2508 hmac_sha256(pass, passlen, u, sizeof(u), u);
2509
2510 for (size_t j=0; j < sizeof(u); j++)
2511 dk[j] ^= u[j];
2512 }
2513
2514 return 0;
2515}