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