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