]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/tpm2-util.c
Merge pull request #29013 from yuwata/sd-dhcp-client-ensure-iaid-and-duid
[thirdparty/systemd.git] / src / shared / tpm2-util.c
CommitLineData
5e521624
LP
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
5e521624 3#include "alloc-util.h"
28db6fbf 4#include "constants.h"
fdf6c27c 5#include "cryptsetup-util.h"
5e521624
LP
6#include "dirent-util.h"
7#include "dlfcn-util.h"
fdf6c27c
LP
8#include "efi-api.h"
9#include "extract-word.h"
5e521624 10#include "fd-util.h"
6a0779cb 11#include "fileio.h"
5e521624
LP
12#include "format-table.h"
13#include "fs-util.h"
14#include "hexdecoct.h"
aae6eb96 15#include "hmac.h"
6270b2e6 16#include "initrd-util.h"
acbb504e 17#include "lock-util.h"
a12bc99e
ZJS
18#include "log.h"
19#include "logarithm.h"
5e521624 20#include "memory-util.h"
6270b2e6 21#include "nulstr-util.h"
fdf6c27c 22#include "parse-util.h"
5e521624 23#include "random-util.h"
2f5a892a 24#include "sha256.h"
323eb480 25#include "sort-util.h"
fdf6c27c 26#include "stat-util.h"
96ead603 27#include "string-table.h"
5e521624 28#include "time-util.h"
fdf6c27c
LP
29#include "tpm2-util.h"
30#include "virt.h"
5e521624 31
fdf6c27c 32#if HAVE_TPM2
5e521624
LP
33static void *libtss2_esys_dl = NULL;
34static void *libtss2_rc_dl = NULL;
35static void *libtss2_mu_dl = NULL;
36
b57a7b3d 37static TSS2_RC (*sym_Esys_Create)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, TPM2B_PRIVATE **outPrivate, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
cea525a9 38static TSS2_RC (*sym_Esys_CreateLoaded)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_TEMPLATE *inPublic, ESYS_TR *objectHandle, TPM2B_PRIVATE **outPrivate, TPM2B_PUBLIC **outPublic) = NULL;
b57a7b3d
DS
39static TSS2_RC (*sym_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext, ESYS_TR primaryHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *inSensitive, const TPM2B_PUBLIC *inPublic, const TPM2B_DATA *outsideInfo, const TPML_PCR_SELECTION *creationPCR, ESYS_TR *objectHandle, TPM2B_PUBLIC **outPublic, TPM2B_CREATION_DATA **creationData, TPM2B_DIGEST **creationHash, TPMT_TK_CREATION **creationTicket) = NULL;
40static TSS2_RC (*sym_Esys_EvictControl)(ESYS_CONTEXT *esysContext, ESYS_TR auth, ESYS_TR objectHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMI_DH_PERSISTENT persistentHandle, ESYS_TR *newObjectHandle) = NULL;
41static void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
42static TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
43static void (*sym_Esys_Free)(void *ptr) = NULL;
44static TSS2_RC (*sym_Esys_GetCapability)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData) = NULL;
45static TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
46static TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
47static TSS2_RC (*sym_Esys_Load)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_PRIVATE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR *objectHandle) = NULL;
48static TSS2_RC (*sym_Esys_LoadExternal)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE *inPrivate, const TPM2B_PUBLIC *inPublic, ESYS_TR hierarchy, ESYS_TR *objectHandle) = NULL;
49static TSS2_RC (*sym_Esys_PCR_Extend)(ESYS_CONTEXT *esysContext, ESYS_TR pcrHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST_VALUES *digests) = NULL;
50static TSS2_RC (*sym_Esys_PCR_Read)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1,ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues) = NULL;
51static TSS2_RC (*sym_Esys_PolicyAuthorize)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *approvedPolicy, const TPM2B_NONCE *policyRef, const TPM2B_NAME *keySign, const TPMT_TK_VERIFIED *checkTicket) = NULL;
52static TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
53static TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
54static TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL;
55static TSS2_RC (*sym_Esys_ReadPublic)(ESYS_CONTEXT *esysContext, ESYS_TR objectHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_PUBLIC **outPublic, TPM2B_NAME **name, TPM2B_NAME **qualifiedName) = NULL;
56static TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL;
57static TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
a47060bb 58static TSS2_RC (*sym_Esys_TestParms)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPMT_PUBLIC_PARMS *parameters) = NULL;
c8a85240 59static TSS2_RC (*sym_Esys_TR_Close)(ESYS_CONTEXT *esys_context, ESYS_TR *rsrc_handle) = NULL;
b57a7b3d
DS
60static TSS2_RC (*sym_Esys_TR_Deserialize)(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle) = NULL;
61static TSS2_RC (*sym_Esys_TR_FromTPMPublic)(ESYS_CONTEXT *esysContext, TPM2_HANDLE tpm_handle, ESYS_TR optionalSession1, ESYS_TR optionalSession2, ESYS_TR optionalSession3, ESYS_TR *object) = NULL;
ba723ea2 62static TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name) = NULL;
b57a7b3d
DS
63static TSS2_RC (*sym_Esys_TR_Serialize)(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size) = NULL;
64static TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
ba723ea2
DS
65static TSS2_RC (*sym_Esys_TRSess_GetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION *flags) = NULL;
66static TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask) = NULL;
b57a7b3d
DS
67static TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL;
68static TSS2_RC (*sym_Esys_VerifySignature)(ESYS_CONTEXT *esysContext, ESYS_TR keyHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *digest, const TPMT_SIGNATURE *signature, TPMT_TK_VERIFIED **validation) = NULL;
69
b57a7b3d
DS
70static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal)(TPM2_CC src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
71static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
72static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
73static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
74static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
75static TSS2_RC (*sym_Tss2_MU_TPML_PCR_SELECTION_Marshal)(TPML_PCR_SELECTION const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
76static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal)(TPMT_HA const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
77static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal)(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
5e521624 78
ba723ea2
DS
79static const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
80
5e521624 81int dlopen_tpm2(void) {
d32f7a8e
ZJS
82 int r;
83
84 r = dlopen_many_sym_or_warn(
85 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
86 DLSYM_ARG(Esys_Create),
cea525a9 87 DLSYM_ARG(Esys_CreateLoaded),
d32f7a8e 88 DLSYM_ARG(Esys_CreatePrimary),
acbb504e 89 DLSYM_ARG(Esys_EvictControl),
d32f7a8e
ZJS
90 DLSYM_ARG(Esys_Finalize),
91 DLSYM_ARG(Esys_FlushContext),
92 DLSYM_ARG(Esys_Free),
07697bfe 93 DLSYM_ARG(Esys_GetCapability),
d32f7a8e
ZJS
94 DLSYM_ARG(Esys_GetRandom),
95 DLSYM_ARG(Esys_Initialize),
96 DLSYM_ARG(Esys_Load),
0d756413 97 DLSYM_ARG(Esys_LoadExternal),
1421943a 98 DLSYM_ARG(Esys_PCR_Extend),
321a9d9e 99 DLSYM_ARG(Esys_PCR_Read),
0d756413 100 DLSYM_ARG(Esys_PolicyAuthorize),
2f5a892a 101 DLSYM_ARG(Esys_PolicyAuthValue),
d32f7a8e
ZJS
102 DLSYM_ARG(Esys_PolicyGetDigest),
103 DLSYM_ARG(Esys_PolicyPCR),
acbb504e 104 DLSYM_ARG(Esys_ReadPublic),
d32f7a8e
ZJS
105 DLSYM_ARG(Esys_StartAuthSession),
106 DLSYM_ARG(Esys_Startup),
a47060bb 107 DLSYM_ARG(Esys_TestParms),
c8a85240 108 DLSYM_ARG(Esys_TR_Close),
ba723ea2 109 DLSYM_ARG(Esys_TR_Deserialize),
acbb504e 110 DLSYM_ARG(Esys_TR_FromTPMPublic),
0d756413 111 DLSYM_ARG(Esys_TR_GetName),
acbb504e 112 DLSYM_ARG(Esys_TR_Serialize),
2f5a892a 113 DLSYM_ARG(Esys_TR_SetAuth),
ba723ea2
DS
114 DLSYM_ARG(Esys_TRSess_GetAttributes),
115 DLSYM_ARG(Esys_TRSess_SetAttributes),
0d756413
LP
116 DLSYM_ARG(Esys_Unseal),
117 DLSYM_ARG(Esys_VerifySignature));
d32f7a8e
ZJS
118 if (r < 0)
119 return r;
120
121 r = dlopen_many_sym_or_warn(
122 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
123 DLSYM_ARG(Tss2_RC_Decode));
124 if (r < 0)
125 return r;
126
127 return dlopen_many_sym_or_warn(
128 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
dcbc4674 129 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
d32f7a8e
ZJS
130 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
131 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
132 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
dbae4b95 133 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
dcbc4674 134 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal),
dbae4b95
DS
135 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal),
136 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal));
5e521624
LP
137}
138
cf1ab844 139static void Esys_Freep(void *p) {
b57a7b3d
DS
140 if (*(void**) p)
141 sym_Esys_Free(*(void**) p);
142}
143
3a35d6cd
DS
144/* Get a specific TPM capability (or capabilities).
145 *
146 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
147 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
148 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
149 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
150 *
151 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
152 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
153 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
154 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
155 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
156 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
157 * capability category may have more specific requirements than described here; see the spec for exact
158 * details. */
159static int tpm2_get_capability(
160 Tpm2Context *c,
161 TPM2_CAP capability,
162 uint32_t property,
163 uint32_t count,
164 TPMU_CAPABILITIES *ret_capability_data) {
165
166 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *capabilities = NULL;
167 TPMI_YES_NO more;
168 TSS2_RC rc;
169
170 assert(c);
171
172 log_debug("Getting TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " count %" PRIu32 ".",
173 capability, property, count);
174
175 rc = sym_Esys_GetCapability(
176 c->esys_context,
177 ESYS_TR_NONE,
178 ESYS_TR_NONE,
179 ESYS_TR_NONE,
180 capability,
181 property,
182 count,
183 &more,
184 &capabilities);
185 if (rc != TSS2_RC_SUCCESS)
186 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
187 "Failed to get TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 ": %s",
188 capability, property, sym_Tss2_RC_Decode(rc));
189
190 if (capabilities->capability != capability)
191 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
192 "TPM provided wrong capability: 0x%04" PRIx32 " instead of 0x%04" PRIx32 ".",
193 capabilities->capability, capability);
194
195 if (ret_capability_data)
196 *ret_capability_data = capabilities->data;
197
198 return more == TPM2_YES;
199}
200
adbf0c8c
DS
201#define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
202
3a35d6cd
DS
203static int tpm2_cache_capabilities(Tpm2Context *c) {
204 TPMU_CAPABILITIES capability;
205 int r;
206
207 assert(c);
208
cbc92a31
DS
209 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
210 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
211 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
212 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
627cdcc7 213 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
cbc92a31
DS
214 * changed while we are performing some operation, it's reasonable to assume it will break us even if
215 * we don't cache the algorithms, thus they should be "safe" to cache. */
216 TPM2_ALG_ID current_alg = TPM2_ALG_FIRST;
217 for (;;) {
218 r = tpm2_get_capability(
219 c,
220 TPM2_CAP_ALGS,
221 (uint32_t) current_alg, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
222 TPM2_MAX_CAP_ALGS,
223 &capability);
224 if (r < 0)
225 return r;
226
227 TPML_ALG_PROPERTY algorithms = capability.algorithms;
228
229 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
230 * there are no more. */
231 assert(algorithms.count > 0);
232
233 if (!GREEDY_REALLOC_APPEND(
234 c->capability_algorithms,
235 c->n_capability_algorithms,
236 algorithms.algProperties,
237 algorithms.count))
238 return log_oom();
239
240 if (r == 0)
241 break;
242
243 /* Set current_alg to alg id after last alg id the TPM provided */
244 current_alg = algorithms.algProperties[algorithms.count - 1].alg + 1;
245 }
246
adbf0c8c 247 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
627cdcc7 248 * while running, but that would be crazy, so let's hope it is not possible. */
adbf0c8c
DS
249 TPM2_CC current_cc = TPM2_CC_FIRST;
250 for (;;) {
251 r = tpm2_get_capability(
252 c,
253 TPM2_CAP_COMMANDS,
254 current_cc,
255 TPM2_MAX_CAP_CC,
256 &capability);
257 if (r < 0)
258 return r;
259
260 TPML_CCA commands = capability.command;
261
262 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
263 * there are no more. */
264 assert(commands.count > 0);
265
266 if (!GREEDY_REALLOC_APPEND(
267 c->capability_commands,
268 c->n_capability_commands,
269 commands.commandAttributes,
270 commands.count))
271 return log_oom();
272
273 if (r == 0)
274 break;
275
276 /* Set current_cc to index after last cc the TPM provided */
277 current_cc = TPMA_CC_TO_TPM2_CC(commands.commandAttributes[commands.count - 1]) + 1;
278 }
279
3a35d6cd
DS
280 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
281 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
282 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
283 * safely assume the TPM PCR allocation will not change while we are using it. */
284 r = tpm2_get_capability(
285 c,
286 TPM2_CAP_PCRS,
287 /* property= */ 0,
288 /* count= */ 1,
289 &capability);
290 if (r < 0)
291 return r;
292 if (r == 1)
293 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
294 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
295 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
296 * this command with the full PCR allocation and moreData will be NO." */
297 log_warning("TPM bug: reported multiple PCR sets; using only first set.");
298 c->capability_pcrs = capability.assignedPCR;
299
300 return 0;
301}
302
cbc92a31
DS
303/* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
304 * TPMA_ALGORITHM is provided, otherwise false. */
305static bool tpm2_get_capability_alg(Tpm2Context *c, TPM2_ALG_ID alg, TPMA_ALGORITHM *ret) {
a47060bb
DS
306 assert(c);
307
cbc92a31
DS
308 FOREACH_ARRAY(alg_prop, c->capability_algorithms, c->n_capability_algorithms)
309 if (alg_prop->alg == alg) {
310 if (ret)
311 *ret = alg_prop->algProperties;
312 return true;
313 }
a47060bb 314
cbc92a31 315 log_debug("TPM does not support alg 0x%02" PRIx16 ".", alg);
a47060bb 316 if (ret)
cbc92a31 317 *ret = 0;
a47060bb 318
cbc92a31 319 return false;
a47060bb
DS
320}
321
cbc92a31 322bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg) {
a47060bb
DS
323 return tpm2_get_capability_alg(c, alg, NULL);
324}
325
adbf0c8c
DS
326/* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
327 * otherwise false. */
328static bool tpm2_get_capability_command(Tpm2Context *c, TPM2_CC command, TPMA_CC *ret) {
329 assert(c);
330
331 FOREACH_ARRAY(cca, c->capability_commands, c->n_capability_commands)
332 if (TPMA_CC_TO_TPM2_CC(*cca) == command) {
333 if (ret)
334 *ret = *cca;
335 return true;
336 }
337
338 log_debug("TPM does not support command 0x%04" PRIx32 ".", command);
339 if (ret)
340 *ret = 0;
341
342 return false;
343}
344
345bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command) {
346 return tpm2_get_capability_command(c, command, NULL);
347}
348
f4f5b3a9
DS
349/* Returns 1 if the TPM supports the ECC curve, 0 if not, or < 0 for any error. */
350static int tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE curve) {
351 TPMU_CAPABILITIES capability;
352 int r;
353
354 /* The spec explicitly states the TPM2_ECC_CURVE should be cast to uint32_t. */
355 r = tpm2_get_capability(c, TPM2_CAP_ECC_CURVES, (uint32_t) curve, 1, &capability);
356 if (r < 0)
357 return r;
358
359 TPML_ECC_CURVE eccCurves = capability.eccCurves;
360 if (eccCurves.count == 0 || eccCurves.eccCurves[0] != curve) {
361 log_debug("TPM does not support ECC curve 0x%02" PRIx16 ".", curve);
362 return 0;
363 }
364
365 return 1;
366}
367
c8a85240
DS
368/* Query the TPM for populated handles.
369 *
370 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
371 * contain only populated handle addresses (which might not include the requested handle). The number of
372 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
373 * range (i.e. handle & 0xff000000).
374 *
375 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
376 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
377static int tpm2_get_capability_handles(
378 Tpm2Context *c,
379 TPM2_HANDLE start,
380 size_t max,
381 TPM2_HANDLE **ret_handles,
382 size_t *ret_n_handles) {
383
384 _cleanup_free_ TPM2_HANDLE *handles = NULL;
385 size_t n_handles = 0;
386 TPM2_HANDLE current = start;
387 int r = 0;
388
389 assert(c);
390 assert(ret_handles);
391 assert(ret_n_handles);
392
393 while (max > 0) {
394 TPMU_CAPABILITIES capability;
395 r = tpm2_get_capability(c, TPM2_CAP_HANDLES, current, (uint32_t) max, &capability);
396 if (r < 0)
397 return r;
398
399 TPML_HANDLE handle_list = capability.handles;
400 if (handle_list.count == 0)
401 break;
402
403 assert(handle_list.count <= max);
404
405 if (n_handles > SIZE_MAX - handle_list.count)
406 return log_oom();
407
408 if (!GREEDY_REALLOC(handles, n_handles + handle_list.count))
409 return log_oom();
410
411 memcpy_safe(&handles[n_handles], handle_list.handle, sizeof(handles[0]) * handle_list.count);
412
413 max -= handle_list.count;
414 n_handles += handle_list.count;
415
416 /* Update current to the handle index after the last handle in the list. */
417 current = handles[n_handles - 1] + 1;
418
419 if (r == 0)
420 /* No more handles in this range. */
421 break;
422 }
423
424 *ret_handles = TAKE_PTR(handles);
425 *ret_n_handles = n_handles;
426
427 return r;
428}
429
430#define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
431#define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
432
433/* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
434static int tpm2_get_capability_handle(Tpm2Context *c, TPM2_HANDLE handle) {
435 _cleanup_free_ TPM2_HANDLE *handles = NULL;
436 size_t n_handles = 0;
437 int r;
438
439 r = tpm2_get_capability_handles(c, handle, 1, &handles, &n_handles);
440 if (r < 0)
441 return r;
442
443 return n_handles == 0 ? false : handles[0] == handle;
444}
445
a47060bb
DS
446/* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
447bool tpm2_test_parms(Tpm2Context *c, TPMI_ALG_PUBLIC alg, const TPMU_PUBLIC_PARMS *parms) {
448 TSS2_RC rc;
449
450 assert(c);
451 assert(parms);
452
453 TPMT_PUBLIC_PARMS parameters = {
454 .type = alg,
455 .parameters = *parms,
456 };
457
458 rc = sym_Esys_TestParms(c->esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parameters);
459 if (rc != TSS2_RC_SUCCESS)
460 /* The spec says if the parms are not supported the TPM returns "...the appropriate
461 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
462 * unmarshaling errors, instead of checking for them all here, let's just assume any error
463 * indicates unsupported parms, and log the specific error text. */
464 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc));
465
466 return rc == TSS2_RC_SUCCESS;
467}
468
cf1ab844 469static bool tpm2_supports_tpmt_public(Tpm2Context *c, const TPMT_PUBLIC *public) {
f4f5b3a9
DS
470 assert(c);
471 assert(public);
472
473 return tpm2_test_parms(c, public->type, &public->parameters);
474}
475
cf1ab844 476static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context *c, const TPMT_SYM_DEF_OBJECT *parameters) {
a47060bb
DS
477 assert(c);
478 assert(parameters);
479
480 TPMU_PUBLIC_PARMS parms = {
481 .symDetail.sym = *parameters,
482 };
483
484 return tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms);
485}
486
cf1ab844 487static bool tpm2_supports_tpmt_sym_def(Tpm2Context *c, const TPMT_SYM_DEF *parameters) {
a47060bb
DS
488 assert(c);
489 assert(parameters);
490
491 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
492 * functionally identical. */
493 TPMT_SYM_DEF_OBJECT object = {
494 .algorithm = parameters->algorithm,
495 .keyBits = parameters->keyBits,
496 .mode = parameters->mode,
497 };
498
499 return tpm2_supports_tpmt_sym_def_object(c, &object);
500}
501
68d084ce
DS
502static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
503 if (!c)
504 return NULL;
5e521624
LP
505
506 if (c->esys_context)
507 sym_Esys_Finalize(&c->esys_context);
508
509 c->tcti_context = mfree(c->tcti_context);
f2592ef0 510 c->tcti_dl = safe_dlclose(c->tcti_dl);
5e521624 511
cbc92a31 512 c->capability_algorithms = mfree(c->capability_algorithms);
adbf0c8c
DS
513 c->capability_commands = mfree(c->capability_commands);
514
68d084ce 515 return mfree(c);
5e521624
LP
516}
517
68d084ce
DS
518DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
519
a47060bb
DS
520static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB = {
521 .algorithm = TPM2_ALG_AES,
522 .keyBits.aes = 128,
523 .mode.aes = TPM2_ALG_CFB, /* The spec requires sessions to use CFB. */
524};
525
68d084ce 526int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
1dc8f518 527 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = NULL;
5e521624
LP
528 TSS2_RC rc;
529 int r;
530
68d084ce
DS
531 assert(ret_context);
532
d70e4bc9 533 context = new(Tpm2Context, 1);
68d084ce
DS
534 if (!context)
535 return log_oom();
536
d70e4bc9
LP
537 *context = (Tpm2Context) {
538 .n_ref = 1,
539 };
68d084ce 540
5e521624
LP
541 r = dlopen_tpm2();
542 if (r < 0)
543 return log_error_errno(r, "TPM2 support not installed: %m");
544
34906680 545 if (!device) {
5e521624 546 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
34906680
LP
547 if (device)
548 /* Setting the env var to an empty string forces tpm2-tss' own device picking
549 * logic to be used. */
550 device = empty_to_null(device);
551 else
552 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
553 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
554 * might be used and we really don't want that, since it is a system service and that creates
555 * various ordering issues/deadlocks during early boot. */
556 device = "device:/dev/tpmrm0";
557 }
5e521624
LP
558
559 if (device) {
560 const char *param, *driver, *fn;
561 const TSS2_TCTI_INFO* info;
562 TSS2_TCTI_INFO_FUNC func;
563 size_t sz = 0;
564
565 param = strchr(device, ':');
566 if (param) {
50a08514 567 /* Syntax #1: Pair of driver string and arbitrary parameter */
2f82562b 568 driver = strndupa_safe(device, param - device);
50a08514
LP
569 if (isempty(driver))
570 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
571
5e521624 572 param++;
50a08514
LP
573 } else if (path_is_absolute(device) && path_is_valid(device)) {
574 /* Syntax #2: TPM device node */
5e521624
LP
575 driver = "device";
576 param = device;
50a08514
LP
577 } else
578 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
579
580 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
5e521624
LP
581
582 fn = strjoina("libtss2-tcti-", driver, ".so.0");
583
50a08514
LP
584 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
585 if (!filename_is_valid(fn))
586 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
587
68d084ce
DS
588 context->tcti_dl = dlopen(fn, RTLD_NOW);
589 if (!context->tcti_dl)
5e521624
LP
590 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
591
68d084ce 592 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
5e521624
LP
593 if (!func)
594 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
595 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
596 dlerror());
597
598 info = func();
599 if (!info)
600 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
601
5e521624
LP
602 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
603
604 rc = info->init(NULL, &sz, NULL);
605 if (rc != TPM2_RC_SUCCESS)
606 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
607 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
608
68d084ce
DS
609 context->tcti_context = malloc0(sz);
610 if (!context->tcti_context)
5e521624
LP
611 return log_oom();
612
68d084ce 613 rc = info->init(context->tcti_context, &sz, param);
5e521624
LP
614 if (rc != TPM2_RC_SUCCESS)
615 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
616 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
617 }
618
68d084ce 619 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
5e521624
LP
620 if (rc != TSS2_RC_SUCCESS)
621 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
622 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
623
68d084ce 624 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
5e521624
LP
625 if (rc == TPM2_RC_INITIALIZE)
626 log_debug("TPM already started up.");
627 else if (rc == TSS2_RC_SUCCESS)
628 log_debug("TPM successfully started up.");
629 else
630 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
631 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
632
3a35d6cd
DS
633 r = tpm2_cache_capabilities(context);
634 if (r < 0)
635 return r;
636
a47060bb 637 /* We require AES and CFB support for session encryption. */
cbc92a31 638 if (!tpm2_supports_alg(context, TPM2_ALG_AES))
a47060bb
DS
639 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES.");
640
cbc92a31 641 if (!tpm2_supports_alg(context, TPM2_ALG_CFB))
a47060bb
DS
642 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support CFB.");
643
644 if (!tpm2_supports_tpmt_sym_def(context, &SESSION_TEMPLATE_SYM_AES_128_CFB))
645 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES-128-CFB.");
646
68d084ce 647 *ret_context = TAKE_PTR(context);
5e521624
LP
648
649 return 0;
650}
651
c8a85240
DS
652static void tpm2_handle_cleanup(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, bool flush) {
653 TSS2_RC rc;
654
16e16b8c
DS
655 if (!esys_context || esys_handle == ESYS_TR_NONE)
656 return;
657
c8a85240
DS
658 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
659 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
660 * as removing its corresponding handle from the actual TPM. */
661 if (flush)
662 rc = sym_Esys_FlushContext(esys_context, esys_handle);
663 else
664 rc = sym_Esys_TR_Close(esys_context, &esys_handle);
16e16b8c
DS
665 if (rc != TSS2_RC_SUCCESS) /* We ignore failures here (besides debug logging), since this is called
666 * in error paths, where we cannot do anything about failures anymore. And
667 * when it is called in successful codepaths by this time we already did
668 * what we wanted to do, and got the results we wanted so there's no
669 * reason to make this fail more loudly than necessary. */
c8a85240 670 log_debug("Failed to %s TPM handle, ignoring: %s", flush ? "flush" : "close", sym_Tss2_RC_Decode(rc));
16e16b8c
DS
671}
672
673Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
674 if (!handle)
675 return NULL;
676
1dc8f518 677 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
c8a85240
DS
678 if (context)
679 tpm2_handle_cleanup(context->esys_context, handle->esys_handle, handle->flush);
16e16b8c
DS
680
681 return mfree(handle);
682}
683
684int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
1dc8f518 685 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
16e16b8c
DS
686
687 assert(ret_handle);
688
d70e4bc9 689 handle = new(Tpm2Handle, 1);
16e16b8c
DS
690 if (!handle)
691 return log_oom();
692
d70e4bc9
LP
693 *handle = (Tpm2Handle) {
694 .tpm2_context = tpm2_context_ref(context),
695 .esys_handle = ESYS_TR_NONE,
c8a85240 696 .flush = true,
d70e4bc9 697 };
16e16b8c
DS
698
699 *ret_handle = TAKE_PTR(handle);
700
701 return 0;
702}
703
c8a85240
DS
704/* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the TPM2_HANDLE address
705 * provided. This should be used only for persistent, transient, or NV handles. Returns 1 on success, 0 if
706 * the requested handle is not present in the TPM, or < 0 on error. */
707static int tpm2_esys_handle_from_tpm_handle(
708 Tpm2Context *c,
709 const Tpm2Handle *session,
710 TPM2_HANDLE tpm_handle,
711 Tpm2Handle **ret_handle) {
712
713 TSS2_RC rc;
714 int r;
715
716 assert(c);
717 assert(tpm_handle > 0);
718 assert(ret_handle);
719
720 /* Let's restrict this, at least for now, to allow only some handle types. */
721 switch (TPM2_HANDLE_TYPE(tpm_handle)) {
722 case TPM2_HT_PERSISTENT:
723 case TPM2_HT_NV_INDEX:
724 case TPM2_HT_TRANSIENT:
725 break;
726 case TPM2_HT_PCR:
727 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
728 "Refusing to create ESYS handle for PCR handle 0x%08" PRIx32 ".",
729 tpm_handle);
730 case TPM2_HT_HMAC_SESSION:
731 case TPM2_HT_POLICY_SESSION:
732 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
733 "Refusing to create ESYS handle for session handle 0x%08" PRIx32 ".",
734 tpm_handle);
735 case TPM2_HT_PERMANENT: /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
736 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
737 "Refusing to create ESYS handle for permanent handle 0x%08" PRIx32 ".",
738 tpm_handle);
739 default:
740 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
741 "Refusing to create ESYS handle for unknown handle 0x%08" PRIx32 ".",
742 tpm_handle);
743 }
744
745 r = tpm2_get_capability_handle(c, tpm_handle);
746 if (r < 0)
747 return r;
748 if (r == 0) {
749 log_debug("TPM handle 0x%08" PRIx32 " not populated.", tpm_handle);
750 *ret_handle = NULL;
751 return 0;
752 }
753
754 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
755 r = tpm2_handle_new(c, &handle);
756 if (r < 0)
757 return r;
758
759 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
760 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
761 handle->flush = false;
762
763 rc = sym_Esys_TR_FromTPMPublic(
764 c->esys_context,
765 tpm_handle,
766 session ? session->esys_handle : ESYS_TR_NONE,
767 ESYS_TR_NONE,
768 ESYS_TR_NONE,
769 &handle->esys_handle);
770 if (rc != TSS2_RC_SUCCESS)
771 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
772 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
773
774 *ret_handle = TAKE_PTR(handle);
775
776 return 1;
777}
778
d2d29c3b
DS
779/* Copy an object in the TPM at a transient location to a persistent location.
780 *
781 * The provided transient handle must exist in the TPM in the transient range. The persistent location may be
782 * 0 or any location in the persistent range. If 0, this will try each handle in the persistent range, in
783 * ascending order, until an available one is found. If non-zero, only the requested persistent location will
784 * be used.
785 *
786 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
787 * location(s), or < 0 on error. The persistent handle is only provided when returning 1. */
788static int tpm2_persist_handle(
789 Tpm2Context *c,
790 const Tpm2Handle *transient_handle,
791 const Tpm2Handle *session,
792 TPMI_DH_PERSISTENT persistent_location,
793 Tpm2Handle **ret_persistent_handle) {
794
795 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
796 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
797 TPMI_DH_PERSISTENT first = UINT32_C(0x81000000), last = UINT32_C(0x81ffffff);
798 TSS2_RC rc;
799 int r;
800
801 assert(c);
802 assert(transient_handle);
803
804 /* If persistent location specified, only try that. */
805 if (persistent_location != 0) {
806 if (TPM2_HANDLE_TYPE(persistent_location) != TPM2_HT_PERSISTENT)
807 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
808 "Handle not in persistent range: 0x%x", persistent_location);
809
810 first = last = persistent_location;
811 }
812
813 for (TPMI_DH_PERSISTENT requested = first; requested <= last; requested++) {
814 _cleanup_(tpm2_handle_freep) Tpm2Handle *persistent_handle = NULL;
815 r = tpm2_handle_new(c, &persistent_handle);
816 if (r < 0)
817 return r;
818
819 /* Since this is a persistent handle, don't flush it. */
820 persistent_handle->flush = false;
821
822 rc = sym_Esys_EvictControl(
823 c->esys_context,
824 ESYS_TR_RH_OWNER,
825 transient_handle->esys_handle,
826 session ? session->esys_handle : ESYS_TR_PASSWORD,
827 ESYS_TR_NONE,
828 ESYS_TR_NONE,
829 requested,
830 &persistent_handle->esys_handle);
831 if (rc == TSS2_RC_SUCCESS) {
832 if (ret_persistent_handle)
833 *ret_persistent_handle = TAKE_PTR(persistent_handle);
834
835 return 1;
836 }
837 if (rc != TPM2_RC_NV_DEFINED)
838 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
839 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc));
840 }
841
842 if (ret_persistent_handle)
843 *ret_persistent_handle = NULL;
844
845 return 0;
846}
847
aba5dac3
LP
848#define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
849
23e9ccc2 850static int tpm2_credit_random(Tpm2Context *c) {
5e521624
LP
851 size_t rps, done = 0;
852 TSS2_RC rc;
aba5dac3 853 usec_t t;
5e521624
LP
854 int r;
855
856 assert(c);
857
858 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
859 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
860 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
861 * any entropy. */
862
aba5dac3
LP
863 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
864 if (errno != ENOENT)
865 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
866 } else {
867 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
868 return 0; /* Already done */
869 }
870
871 t = now(CLOCK_MONOTONIC);
872
5e521624
LP
873 for (rps = random_pool_size(); rps > 0;) {
874 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
875
876 rc = sym_Esys_GetRandom(
23e9ccc2 877 c->esys_context,
5e521624
LP
878 ESYS_TR_NONE,
879 ESYS_TR_NONE,
880 ESYS_TR_NONE,
881 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
882 &buffer);
883 if (rc != TSS2_RC_SUCCESS)
884 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
885 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
886
887 if (buffer->size == 0)
888 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
889 "Zero-sized entropy returned from TPM.");
890
aba5dac3 891 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
5e521624
LP
892 if (r < 0)
893 return log_error_errno(r, "Failed wo write entropy to kernel: %m");
894
895 done += buffer->size;
896 rps = LESS_BY(rps, buffer->size);
897 }
898
aba5dac3
LP
899 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
900
901 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
902 if (r < 0)
903 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
904
5e521624
LP
905 return 0;
906}
907
98d6a809
DS
908static int tpm2_read_public(
909 Tpm2Context *c,
910 const Tpm2Handle *session,
911 const Tpm2Handle *handle,
912 TPM2B_PUBLIC **ret_public,
913 TPM2B_NAME **ret_name,
914 TPM2B_NAME **ret_qname) {
915
916 TSS2_RC rc;
917
918 assert(c);
919 assert(handle);
920
921 rc = sym_Esys_ReadPublic(
922 c->esys_context,
923 handle->esys_handle,
924 session ? session->esys_handle : ESYS_TR_NONE,
925 ESYS_TR_NONE,
926 ESYS_TR_NONE,
927 ret_public,
928 ret_name,
929 ret_qname);
930 if (rc != TSS2_RC_SUCCESS)
931 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
932 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
933
934 return 0;
935}
936
f4f5b3a9
DS
937/* Get one of the legacy primary key templates.
938 *
939 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
940 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
941 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
942 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
943static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
944 /* Do not modify. */
945 static const TPMT_PUBLIC legacy_ecc = {
946 .type = TPM2_ALG_ECC,
947 .nameAlg = TPM2_ALG_SHA256,
948 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
949 .parameters.eccDetail = {
950 .symmetric = {
951 .algorithm = TPM2_ALG_AES,
952 .keyBits.aes = 128,
953 .mode.aes = TPM2_ALG_CFB,
5e521624 954 },
f4f5b3a9
DS
955 .scheme.scheme = TPM2_ALG_NULL,
956 .curveID = TPM2_ECC_NIST_P256,
957 .kdf.scheme = TPM2_ALG_NULL,
5e521624 958 },
f4f5b3a9
DS
959 };
960
961 /* Do not modify. */
962 static const TPMT_PUBLIC legacy_rsa = {
963 .type = TPM2_ALG_RSA,
964 .nameAlg = TPM2_ALG_SHA256,
965 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
966 .parameters.rsaDetail = {
967 .symmetric = {
968 .algorithm = TPM2_ALG_AES,
969 .keyBits.aes = 128,
970 .mode.aes = TPM2_ALG_CFB,
acbb504e 971 },
f4f5b3a9
DS
972 .scheme.scheme = TPM2_ALG_NULL,
973 .keyBits = 2048,
acbb504e 974 },
f4f5b3a9
DS
975 };
976
977 assert(ret_template);
978
979 if (alg == TPM2_ALG_ECC)
980 *ret_template = legacy_ecc;
981 else if (alg == TPM2_ALG_RSA)
982 *ret_template = legacy_rsa;
983 else
984 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
985 "Unsupported legacy SRK alg: 0x%x", alg);
986
987 return 0;
988}
989
990/* Get a Storage Root Key (SRK) template.
991 *
992 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
993 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
994 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
995 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
996 * "L-2" (for ECC).
997 *
998 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
999 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1000 *
1001 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1002 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1003 * (see TPM2_SRK_HANDLE and tpm2_get_srk() below).
1004 *
1005 * The alg must be TPM2_ALG_RSA or TPM2_ALG_ECC. Returns error if the requested template is not supported on
cea525a9 1006 * this TPM. Also see tpm2_get_best_srk_template() below. */
f4f5b3a9
DS
1007static int tpm2_get_srk_template(Tpm2Context *c, TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1008 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1009 * Provisioning Guidance document, specifically:
1010 * TPMA_OBJECT_USERWITHAUTH is added.
1011 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1012 * TPMA_OBJECT_NODA is added. */
1013 TPMA_OBJECT srk_attributes =
1014 TPMA_OBJECT_DECRYPT |
1015 TPMA_OBJECT_FIXEDPARENT |
1016 TPMA_OBJECT_FIXEDTPM |
1017 TPMA_OBJECT_NODA |
1018 TPMA_OBJECT_RESTRICTED |
1019 TPMA_OBJECT_SENSITIVEDATAORIGIN |
1020 TPMA_OBJECT_USERWITHAUTH;
1021
1022 /* The symmetric configuration is the same between ECC and RSA templates. */
1023 TPMT_SYM_DEF_OBJECT srk_symmetric = {
1024 .algorithm = TPM2_ALG_AES,
1025 .keyBits.aes = 128,
1026 .mode.aes = TPM2_ALG_CFB,
1027 };
1028
1029 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1030
1031 /* From the EK Credential Profile template "L-2". */
1032 TPMT_PUBLIC srk_ecc = {
1033 .type = TPM2_ALG_ECC,
1034 .nameAlg = TPM2_ALG_SHA256,
1035 .objectAttributes = srk_attributes,
1036 .parameters.eccDetail = {
1037 .symmetric = srk_symmetric,
1038 .scheme.scheme = TPM2_ALG_NULL,
1039 .curveID = TPM2_ECC_NIST_P256,
1040 .kdf.scheme = TPM2_ALG_NULL,
acbb504e 1041 },
f4f5b3a9
DS
1042 };
1043
1044 /* From the EK Credential Profile template "L-1". */
1045 TPMT_PUBLIC srk_rsa = {
1046 .type = TPM2_ALG_RSA,
1047 .nameAlg = TPM2_ALG_SHA256,
1048 .objectAttributes = srk_attributes,
1049 .parameters.rsaDetail = {
1050 .symmetric = srk_symmetric,
1051 .scheme.scheme = TPM2_ALG_NULL,
1052 .keyBits = 2048,
2b92a672
LP
1053 },
1054 };
1055
f4f5b3a9
DS
1056 assert(c);
1057 assert(ret_template);
1058
1059 if (alg == TPM2_ALG_ECC) {
1060 if (!tpm2_supports_alg(c, TPM2_ALG_ECC))
1061 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1062 "TPM does not support ECC.");
1063
1064 if (!tpm2_supports_ecc_curve(c, srk_ecc.parameters.eccDetail.curveID))
1065 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1066 "TPM does not support ECC-NIST-P256 curve.");
1067
1068 if (!tpm2_supports_tpmt_public(c, &srk_ecc))
1069 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1070 "TPM does not support SRK ECC template L-2.");
1071
1072 *ret_template = srk_ecc;
1073 return 0;
1074 }
1075
1076 if (alg == TPM2_ALG_RSA) {
1077 if (!tpm2_supports_alg(c, TPM2_ALG_RSA))
1078 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1079 "TPM does not support RSA.");
1080
1081 if (!tpm2_supports_tpmt_public(c, &srk_rsa))
1082 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1083 "TPM does not support SRK RSA template L-1.");
1084
1085 *ret_template = srk_rsa;
1086 return 0;
1087 }
1088
1089 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported SRK alg: 0x%x.", alg);
acbb504e
WR
1090}
1091
cea525a9
DS
1092/* Get the best supported SRK template. ECC is preferred, then RSA. */
1093static int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template) {
1094 if (tpm2_get_srk_template(c, TPM2_ALG_ECC, ret_template) >= 0 ||
1095 tpm2_get_srk_template(c, TPM2_ALG_RSA, ret_template) >= 0)
1096 return 0;
1097
1098 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1099 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1100}
1101
f4f5b3a9
DS
1102/* The SRK handle is defined in the Provisioning Guidance document (see above) in the table "Reserved Handles
1103 * for TPM Provisioning Fundamental Elements". The SRK is useful because it is "shared", meaning it has no
1104 * authValue nor authPolicy set, and thus may be used by anyone on the system to generate derived keys or
1105 * seal secrets. This is useful if the TPM has an auth (password) set for the 'owner hierarchy', which would
1106 * prevent users from generating primary transient keys, unless they knew the owner hierarchy auth. See
1107 * the Provisioning Guidance document for more details. */
1108#define TPM2_SRK_HANDLE UINT32_C(0x81000001)
acbb504e 1109
cea525a9
DS
1110/* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1111 * tpm2_get_or_create_srk() below. */
acbb504e
WR
1112static int tpm2_get_srk(
1113 Tpm2Context *c,
c8a85240 1114 const Tpm2Handle *session,
98d6a809
DS
1115 TPM2B_PUBLIC **ret_public,
1116 TPM2B_NAME **ret_name,
1117 TPM2B_NAME **ret_qname,
c8a85240 1118 Tpm2Handle **ret_handle) {
acbb504e 1119
c8a85240 1120 int r;
acbb504e
WR
1121
1122 assert(c);
acbb504e 1123
c8a85240 1124 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
f4f5b3a9 1125 r = tpm2_esys_handle_from_tpm_handle(c, session, TPM2_SRK_HANDLE, &handle);
c8a85240
DS
1126 if (r < 0)
1127 return r;
1128 if (r == 0) { /* SRK not found */
98d6a809
DS
1129 if (ret_public)
1130 *ret_public = NULL;
1131 if (ret_name)
1132 *ret_name = NULL;
1133 if (ret_qname)
1134 *ret_qname = NULL;
c8a85240
DS
1135 if (ret_handle)
1136 *ret_handle = NULL;
acbb504e
WR
1137 return 0;
1138 }
1139
98d6a809
DS
1140 if (ret_public || ret_name || ret_qname) {
1141 r = tpm2_read_public(c, session, handle, ret_public, ret_name, ret_qname);
1142 if (r < 0)
1143 return r;
acbb504e
WR
1144 }
1145
c8a85240
DS
1146 if (ret_handle)
1147 *ret_handle = TAKE_PTR(handle);
acbb504e 1148
acbb504e
WR
1149 return 1;
1150}
1151
cea525a9
DS
1152/* Get the SRK, creating one if needed. Returns 0 on success, or < 0 on error. */
1153static int tpm2_get_or_create_srk(
1154 Tpm2Context *c,
1155 const Tpm2Handle *session,
1156 TPM2B_PUBLIC **ret_public,
1157 TPM2B_NAME **ret_name,
1158 TPM2B_NAME **ret_qname,
1159 Tpm2Handle **ret_handle) {
1160
1161 int r;
1162
1163 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1164 if (r < 0)
1165 return r;
1166 if (r == 1)
1167 return 0;
1168
1169 /* No SRK, create and persist one */
aff853f8
DS
1170 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
1171 r = tpm2_get_best_srk_template(c, &template.publicArea);
cea525a9
DS
1172 if (r < 0)
1173 return log_error_errno(r, "Could not get best SRK template: %m");
1174
1175 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
aff853f8 1176 r = tpm2_create_primary(
cea525a9 1177 c,
cea525a9
DS
1178 session,
1179 &template,
1180 /* sensitive= */ NULL,
1181 /* ret_public= */ NULL,
cea525a9
DS
1182 &transient_handle);
1183 if (r < 0)
1184 return r;
1185
1186 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1187 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1188 * either case, all threads will get the persistent SRK below. */
1189 r = tpm2_persist_handle(c, transient_handle, session, TPM2_SRK_HANDLE, /* ret_persistent_handle= */ NULL);
1190 if (r < 0)
1191 return r;
1192
1193 /* The SRK should exist now. */
1194 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1195 if (r < 0)
1196 return r;
1197 if (r == 0)
1198 /* This should never happen. */
1199 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SRK we just persisted couldn't be found.");
1200
1201 return 0;
1202}
1203
c69bd0ab
DS
1204/* Utility functions for TPMS_PCR_SELECTION. */
1205
1206/* Convert a TPMS_PCR_SELECTION object to a mask. */
dbaae766 1207uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s) {
c69bd0ab
DS
1208 assert(s);
1209 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
321a9d9e 1210
c69bd0ab
DS
1211 uint32_t mask = 0;
1212 for (unsigned i = 0; i < s->sizeofSelect; i++)
1213 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
dbaae766 1214 return mask;
c69bd0ab 1215}
321a9d9e 1216
c69bd0ab
DS
1217/* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1218void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
1219 assert(ret);
1220
1221 /* This is currently hardcoded at 24 PCRs, above. */
1222 if (!TPM2_PCR_MASK_VALID(mask))
1223 log_warning("PCR mask selections (%x) out of range, ignoring.",
1224 mask & ~((uint32_t)TPM2_PCRS_MASK));
1225
1226 *ret = (TPMS_PCR_SELECTION){
1227 .hash = hash_alg,
1228 .sizeofSelect = TPM2_PCRS_MAX / 8,
1229 .pcrSelect[0] = mask & 0xff,
1230 .pcrSelect[1] = (mask >> 8) & 0xff,
1231 .pcrSelect[2] = (mask >> 16) & 0xff,
1232 };
1233}
1234
13b55174
DS
1235/* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1236bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION *s, uint32_t mask) {
1237 assert(s);
1238
1239 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s), mask);
1240}
1241
1242static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION *s, uint32_t mask, bool b) {
1243 assert(s);
1244
1245 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s), mask, b), s->hash, s);
1246}
1247
1248/* Add all PCR selections in the mask. */
1249void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1250 tpm2_tpms_pcr_selection_update_mask(s, mask, 1);
1251}
1252
1253/* Remove all PCR selections in the mask. */
1254void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1255 tpm2_tpms_pcr_selection_update_mask(s, mask, 0);
1256}
1257
c69bd0ab
DS
1258/* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1259void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1260 assert(a);
1261 assert(b);
1262 assert(a->hash == b->hash);
1263
13b55174 1264 tpm2_tpms_pcr_selection_add_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
c69bd0ab
DS
1265}
1266
1267/* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1268void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1269 assert(a);
1270 assert(b);
1271 assert(a->hash == b->hash);
1272
13b55174 1273 tpm2_tpms_pcr_selection_sub_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
c69bd0ab
DS
1274}
1275
1276/* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1277void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
1278 if (a == b)
1279 return;
1280
1281 tpm2_tpms_pcr_selection_add(a, b);
1282 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
1283}
1284
193fd573
DS
1285#define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1286 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1287#define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1288 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1289 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1290
c69bd0ab 1291#define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
dbaae766 1292 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
c69bd0ab 1293
c69bd0ab
DS
1294#define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1295 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1296 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1297
1298char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
1299 assert(s);
1300
1301 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
1302
dbaae766
DS
1303 _cleanup_free_ char *mask = tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s));
1304 if (!mask)
c69bd0ab
DS
1305 return NULL;
1306
dbaae766 1307 return strjoin(algstr, "(", mask, ")");
c69bd0ab
DS
1308}
1309
1310size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
1311 assert(s);
1312
dbaae766 1313 return popcount(tpm2_tpms_pcr_selection_to_mask(s));
c69bd0ab
DS
1314}
1315
1316/* Utility functions for TPML_PCR_SELECTION. */
1317
1318/* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1319static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
1320 assert(l);
9afd4dde 1321 assert(l->count <= ELEMENTSOF(l->pcrSelections));
c69bd0ab
DS
1322 assert(index < l->count);
1323
1324 size_t s = l->count - (index + 1);
1325 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
1326 l->count--;
1327}
1328
1329/* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1330 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1331 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1332static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1333 TPML_PCR_SELECTION *l,
1334 TPMI_ALG_HASH hash_alg) {
1335
1336 assert(l);
9afd4dde 1337 assert(l->count <= ELEMENTSOF(l->pcrSelections));
c69bd0ab
DS
1338
1339 TPMS_PCR_SELECTION *selection = NULL;
1340 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1341 if (s->hash == hash_alg) {
1342 selection = s;
1343 break;
1344 }
1345
1346 if (!selection)
1347 return NULL;
1348
1349 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1350 for (uint32_t i = l->count - 1; i > 0; i--) {
1351 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
1352
1353 if (selection == s)
1354 break;
1355
1356 if (s->hash == hash_alg) {
1357 tpm2_tpms_pcr_selection_move(selection, s);
1358 tpm2_tpml_pcr_selection_remove_index(l, i);
4dde902e 1359 }
c69bd0ab
DS
1360 }
1361
1362 return selection;
1363}
1364
193fd573
DS
1365/* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1366static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
1367 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1368 for (uint32_t i = 0; i < l->count; i++)
1369 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1370 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, l->pcrSelections[i].hash);
1371}
1372
dbaae766
DS
1373/* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1374uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg) {
c69bd0ab 1375 assert(l);
c69bd0ab
DS
1376
1377 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1378 * are multiple entries with the requested hash alg. */
1379 TPML_PCR_SELECTION lcopy = *l;
1380
1381 TPMS_PCR_SELECTION *s;
1382 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
1383 if (!s)
dbaae766 1384 return 0;
c69bd0ab 1385
dbaae766 1386 return tpm2_tpms_pcr_selection_to_mask(s);
c69bd0ab
DS
1387}
1388
1389/* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1390void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
1391 assert(ret);
1392
1393 TPMS_PCR_SELECTION s;
1394 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
1395
1396 *ret = (TPML_PCR_SELECTION){
1397 .count = 1,
1398 .pcrSelections[0] = s,
321a9d9e
LP
1399 };
1400}
1401
c69bd0ab
DS
1402/* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1403 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1404 * entries with the same hash alg. */
1405void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1406 assert(l);
1407 assert(s);
1408
1409 if (tpm2_tpms_pcr_selection_is_empty(s))
1410 return;
1411
1412 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1413 if (selection) {
1414 tpm2_tpms_pcr_selection_add(selection, s);
1415 return;
1416 }
1417
1418 /* It's already broken if the count is higher than the array has size for. */
9afd4dde 1419 assert(l->count <= ELEMENTSOF(l->pcrSelections));
c69bd0ab
DS
1420
1421 /* If full, the cleanup should result in at least one available entry. */
9afd4dde 1422 if (l->count == ELEMENTSOF(l->pcrSelections))
c69bd0ab
DS
1423 tpm2_tpml_pcr_selection_cleanup(l);
1424
9afd4dde 1425 assert(l->count < ELEMENTSOF(l->pcrSelections));
c69bd0ab
DS
1426 l->pcrSelections[l->count++] = *s;
1427}
1428
1429/* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1430 * will combine all entries for 's->hash' in 'l'. */
1431void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1432 assert(l);
1433 assert(s);
1434
1435 if (tpm2_tpms_pcr_selection_is_empty(s))
1436 return;
1437
1438 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1439 if (selection)
1440 tpm2_tpms_pcr_selection_sub(selection, s);
1441}
1442
13b55174
DS
1443/* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1444bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1445 assert(l);
1446
1447 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l, hash), mask);
1448}
1449
1450/* Add the PCR selections in the mask, with the provided hash. */
1451void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1452 TPMS_PCR_SELECTION tpms;
1453
1454 assert(l);
1455
1456 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1457 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l, &tpms);
1458}
1459
1460/* Remove the PCR selections in the mask, with the provided hash. */
1461void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1462 TPMS_PCR_SELECTION tpms;
1463
1464 assert(l);
1465
1466 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1467 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l, &tpms);
1468}
1469
c69bd0ab
DS
1470/* Add all PCR selections in 'b' to 'a'. */
1471void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1472 assert(a);
1473 assert(b);
1474
193fd573 1475 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
c69bd0ab
DS
1476 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
1477}
1478
1479/* Remove all PCR selections in 'b' from 'a'. */
1480void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1481 assert(a);
1482 assert(b);
1483
193fd573 1484 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
c69bd0ab
DS
1485 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
1486}
1487
1488char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
1489 assert(l);
1490
1491 _cleanup_free_ char *banks = NULL;
193fd573 1492 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
c69bd0ab
DS
1493 if (tpm2_tpms_pcr_selection_is_empty(s))
1494 continue;
1495
1496 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
1497 if (!str || !strextend_with_separator(&banks, ",", str))
1498 return NULL;
1499 }
1500
1501 return strjoin("[", strempty(banks), "]");
1502}
1503
1504size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
1505 assert(l);
9afd4dde 1506 assert(l->count <= ELEMENTSOF(l->pcrSelections));
c69bd0ab
DS
1507
1508 size_t weight = 0;
1509 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1510 size_t w = tpm2_tpms_pcr_selection_weight(s);
1511 assert(weight <= SIZE_MAX - w);
1512 weight += w;
1513 }
1514
1515 return weight;
1516}
1517
cc1a78d5 1518bool tpm2_pcr_value_valid(const Tpm2PCRValue *pcr_value) {
323eb480
DS
1519 int r;
1520
064ac95d
DS
1521 if (!pcr_value)
1522 return false;
323eb480
DS
1523
1524 if (!TPM2_PCR_INDEX_VALID(pcr_value->index)) {
1525 log_debug("PCR index %u invalid.", pcr_value->index);
1526 return false;
1527 }
1528
1529 /* If it contains a value, the value size must match the hash size. */
1530 if (pcr_value->value.size > 0) {
1531 r = tpm2_hash_alg_to_size(pcr_value->hash);
1532 if (r < 0)
1533 return false;
1534
3cd4145f 1535 if (pcr_value->value.size != (size_t) r) {
323eb480
DS
1536 log_debug("PCR hash 0x%" PRIx16 " expected size %d does not match actual size %" PRIu16 ".",
1537 pcr_value->hash, r, pcr_value->value.size);
1538 return false;
1539 }
1540 }
1541
1542 return true;
1543}
1544
1545/* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1546 *
1547 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1548 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
064ac95d
DS
1549 *
1550 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
323eb480 1551 */
cc1a78d5 1552bool tpm2_pcr_values_valid(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
064ac95d
DS
1553 if (!pcr_values && n_pcr_values > 0)
1554 return false;
323eb480 1555
193fd573
DS
1556 const Tpm2PCRValue *previous = NULL;
1557 FOREACH_ARRAY(current, pcr_values, n_pcr_values) {
1558 if (!tpm2_pcr_value_valid(current))
323eb480
DS
1559 return false;
1560
193fd573
DS
1561 if (!previous) {
1562 previous = current;
323eb480 1563 continue;
193fd573 1564 }
323eb480
DS
1565
1566 /* Hashes must be sorted in ascending order */
193fd573 1567 if (current->hash < previous->hash) {
323eb480 1568 log_debug("PCR values not in ascending order, hash %" PRIu16 " is after %" PRIu16 ".",
193fd573 1569 current->hash, previous->hash);
323eb480
DS
1570 return false;
1571 }
1572
193fd573 1573 if (current->hash == previous->hash) {
323eb480 1574 /* Indexes (for the same hash) must be sorted in ascending order */
193fd573 1575 if (current->index < previous->index) {
323eb480 1576 log_debug("PCR values not in ascending order, hash %" PRIu16 " index %u is after %u.",
193fd573 1577 current->hash, current->index, previous->index);
323eb480
DS
1578 return false;
1579 }
1580
1581 /* Indexes (for the same hash) must not be duplicates */
193fd573 1582 if (current->index == previous->index) {
323eb480 1583 log_debug("PCR values contain duplicates for hash %" PRIu16 " index %u.",
193fd573 1584 current->hash, previous->index);
323eb480
DS
1585 return false;
1586 }
1587 }
1588 }
1589
1590 return true;
1591}
1592
26d8d71f
DS
1593/* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1594bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1595 assert(pcr_values || n_pcr_values == 0);
1596
1597 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1598 if (v->value.size > 0)
1599 return true;
1600
1601 return false;
1602}
1603
1604/* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1605bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1606 assert(pcr_values || n_pcr_values == 0);
1607
1608 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1609 if (v->value.size == 0)
1610 return false;
1611
1612 return true;
1613}
1614
323eb480
DS
1615static int cmp_pcr_values(const Tpm2PCRValue *a, const Tpm2PCRValue *b) {
1616 assert(a);
1617 assert(b);
1618
1619 return CMP(a->hash, b->hash) ?: CMP(a->index, b->index);
1620}
1621
1622/* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1623 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1624void tpm2_sort_pcr_values(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1625 typesafe_qsort(pcr_values, n_pcr_values, cmp_pcr_values);
1626}
1627
1628int tpm2_pcr_values_from_mask(uint32_t mask, TPMI_ALG_HASH hash, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1629 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1630 size_t n_pcr_values = 0;
1631
1632 assert(ret_pcr_values);
1633 assert(ret_n_pcr_values);
1634
1635 FOREACH_PCR_IN_MASK(index, mask)
1636 if (!GREEDY_REALLOC_APPEND(
1637 pcr_values,
1638 n_pcr_values,
1639 &TPM2_PCR_VALUE_MAKE(index, hash, {}),
1640 1))
1641 return log_oom_debug();
1642
1643 *ret_pcr_values = TAKE_PTR(pcr_values);
1644 *ret_n_pcr_values = n_pcr_values;
1645
1646 return 0;
1647}
1648
1649int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPMI_ALG_HASH hash, uint32_t *ret_mask) {
1650 uint32_t mask = 0;
1651
1652 assert(pcr_values || n_pcr_values == 0);
1653 assert(ret_mask);
1654
cc1a78d5 1655 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
323eb480
DS
1656 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PCR values.");
1657
193fd573
DS
1658 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1659 if (v->hash == hash)
1660 SET_BIT(mask, v->index);
323eb480
DS
1661
1662 *ret_mask = mask;
1663
1664 return 0;
1665}
1666
1667int tpm2_tpml_pcr_selection_from_pcr_values(
1668 const Tpm2PCRValue *pcr_values,
1669 size_t n_pcr_values,
1670 TPML_PCR_SELECTION *ret_selection,
1671 TPM2B_DIGEST **ret_values,
1672 size_t *ret_n_values) {
1673
1674 TPML_PCR_SELECTION selection = {};
1675 _cleanup_free_ TPM2B_DIGEST *values = NULL;
1676 size_t n_values = 0;
1677
1678 assert(pcr_values || n_pcr_values == 0);
1679
cc1a78d5 1680 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
323eb480
DS
1681 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "PCR values are not valid.");
1682
193fd573
DS
1683 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1684 tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
323eb480 1685
193fd573 1686 if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
323eb480
DS
1687 return log_oom_debug();
1688 }
1689
1690 if (ret_selection)
1691 *ret_selection = selection;
1692 if (ret_values)
1693 *ret_values = TAKE_PTR(values);
1694 if (ret_n_values)
1695 *ret_n_values = n_values;
1696
1697 return 0;
1698}
1699
1700/* Count the number of different hash algorithms for all the entries. */
1701int tpm2_pcr_values_hash_count(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, size_t *ret_count) {
1702 TPML_PCR_SELECTION selection;
1703 int r;
1704
1705 assert(pcr_values);
1706 assert(ret_count);
1707
1708 r = tpm2_tpml_pcr_selection_from_pcr_values(
1709 pcr_values,
1710 n_pcr_values,
1711 &selection,
1712 /* ret_values= */ NULL,
1713 /* ret_n_values= */ NULL);
1714 if (r < 0)
1715 return r;
1716
1717 *ret_count = selection.count;
1718
1719 return 0;
1720}
1721
1722/* Parse a string argument into a Tpm2PCRValue object.
1723 *
1724 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1725 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1726 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1727int tpm2_pcr_value_from_string(const char *arg, Tpm2PCRValue *ret_pcr_value) {
1728 Tpm2PCRValue pcr_value = {};
1729 const char *p = arg;
1730 int r;
1731
1732 assert(arg);
1733 assert(ret_pcr_value);
1734
1735 _cleanup_free_ char *index = NULL;
1736 r = extract_first_word(&p, &index, ":", /* flags= */ 0);
1737 if (r < 1)
1738 return log_error_errno(r, "Could not parse pcr value '%s': %m", p);
1739
2099cd62 1740 r = tpm2_pcr_index_from_string(index);
323eb480
DS
1741 if (r < 0)
1742 return log_error_errno(r, "Invalid pcr index '%s': %m", index);
1743 pcr_value.index = (unsigned) r;
1744
1745 if (!isempty(p)) {
1746 _cleanup_free_ char *hash = NULL;
1747 r = extract_first_word(&p, &hash, "=", /* flags= */ 0);
1748 if (r < 1)
1749 return log_error_errno(r, "Could not parse pcr hash algorithm '%s': %m", p);
1750
1751 r = tpm2_hash_alg_from_string(hash);
1752 if (r < 0)
1753 return log_error_errno(r, "Invalid pcr hash algorithm '%s': %m", hash);
1754 pcr_value.hash = (TPMI_ALG_HASH) r;
323eb480 1755
2b2ee3f2
DS
1756 if (!isempty(p)) {
1757 /* Remove leading 0x if present */
1758 p = startswith_no_case(p, "0x") ?: p;
323eb480 1759
2b2ee3f2
DS
1760 _cleanup_free_ void *buf = NULL;
1761 size_t buf_size = 0;
1762 r = unhexmem(p, SIZE_MAX, &buf, &buf_size);
1763 if (r < 0)
1764 return log_error_errno(r, "Invalid pcr hash value '%s': %m", p);
323eb480 1765
2b2ee3f2
DS
1766 r = TPM2B_DIGEST_CHECK_SIZE(buf_size);
1767 if (r < 0)
1768 return log_error_errno(r, "PCR hash value size %zu too large.", buf_size);
53b91e19 1769
2b2ee3f2
DS
1770 pcr_value.value = TPM2B_DIGEST_MAKE(buf, buf_size);
1771 }
323eb480
DS
1772 }
1773
1774 *ret_pcr_value = pcr_value;
1775
1776 return 0;
1777}
1778
1779/* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1780 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1781 * string. This does not check for validity. */
1782char *tpm2_pcr_value_to_string(const Tpm2PCRValue *pcr_value) {
1783 _cleanup_free_ char *index = NULL, *value = NULL;
323eb480 1784
495f2bf5 1785 if (asprintf(&index, "%u", pcr_value->index) < 0)
323eb480
DS
1786 return NULL;
1787
8e757259 1788 const char *hash = pcr_value->hash > 0 ? tpm2_hash_alg_to_string(pcr_value->hash) : NULL;
323eb480
DS
1789
1790 if (hash && pcr_value->value.size > 0) {
1791 value = hexmem(pcr_value->value.buffer, pcr_value->value.size);
1792 if (!value)
1793 return NULL;
1794 }
1795
85b6f299 1796 return strjoin(index, hash ? ":" : "", strempty(hash), value ? "=" : "", strempty(value));
323eb480
DS
1797}
1798
1799/* Parse a string argument into an array of Tpm2PCRValue objects.
1800 *
1801 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1802 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1803int tpm2_pcr_values_from_string(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1804 const char *p = arg;
1805 int r;
1806
1807 assert(arg);
1808 assert(ret_pcr_values);
1809 assert(ret_n_pcr_values);
1810
1811 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1812 size_t n_pcr_values = 0;
1813
1814 for (;;) {
1815 _cleanup_free_ char *pcr_arg = NULL;
1816 r = extract_first_word(&p, &pcr_arg, ",+", /* flags= */ 0);
1817 if (r < 0)
1818 return log_error_errno(r, "Could not parse pcr values '%s': %m", p);
1819 if (r == 0)
1820 break;
1821
1822 Tpm2PCRValue pcr_value;
1823 r = tpm2_pcr_value_from_string(pcr_arg, &pcr_value);
1824 if (r < 0)
1825 return r;
1826
1827 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
1828 return log_oom();
1829 }
1830
1831 *ret_pcr_values = TAKE_PTR(pcr_values);
1832 *ret_n_pcr_values = n_pcr_values;
1833
1834 return 0;
1835}
1836
1837/* Return a string representing the array of PCR values. The format is as described in
1838 * tpm2_pcr_values_from_string(). This does not check for validity. */
1839char *tpm2_pcr_values_to_string(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1840 _cleanup_free_ char *s = NULL;
1841
193fd573
DS
1842 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1843 _cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(v);
323eb480
DS
1844 if (!pcrstr || !strextend_with_separator(&s, "+", pcrstr))
1845 return NULL;
1846 }
1847
1848 return s ? TAKE_PTR(s) : strdup("");
1849}
1850
75de375a 1851void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
c57d8bc8
DS
1852 if (!DEBUG_LOGGING || !l)
1853 return;
1854
1855 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
1856 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
1857}
1858
75de375a 1859void tpm2_log_debug_pcr_value(const Tpm2PCRValue *pcr_value, const char *msg) {
323eb480
DS
1860 if (!DEBUG_LOGGING || !pcr_value)
1861 return;
1862
1863 _cleanup_free_ char *s = tpm2_pcr_value_to_string(pcr_value);
1864 log_debug("%s: %s", msg ?: "PCR value", strna(s));
1865}
1866
75de375a 1867void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
23b972d5
DS
1868 if (!DEBUG_LOGGING || !buffer || size == 0)
1869 return;
1870
1871 _cleanup_free_ char *h = hexmem(buffer, size);
1872 log_debug("%s: %s", msg ?: "Buffer", strna(h));
1873}
1874
75de375a 1875void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
23b972d5
DS
1876 if (digest)
1877 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
1878}
1879
75de375a 1880void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
dbae4b95
DS
1881 if (name)
1882 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
1883}
1884
23b972d5
DS
1885static int tpm2_get_policy_digest(
1886 Tpm2Context *c,
1887 const Tpm2Handle *session,
1888 TPM2B_DIGEST **ret_policy_digest) {
1889
1890 TSS2_RC rc;
1891
1892 if (!DEBUG_LOGGING && !ret_policy_digest)
1893 return 0;
1894
1895 assert(c);
1896 assert(session);
1897
1898 log_debug("Acquiring policy digest.");
1899
1900 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
1901 rc = sym_Esys_PolicyGetDigest(
1902 c->esys_context,
1903 session->esys_handle,
1904 ESYS_TR_NONE,
1905 ESYS_TR_NONE,
1906 ESYS_TR_NONE,
1907 &policy_digest);
1908 if (rc != TSS2_RC_SUCCESS)
1909 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1910 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
1911
1912 tpm2_log_debug_digest(policy_digest, "Session policy digest");
1913
1914 if (ret_policy_digest)
1915 *ret_policy_digest = TAKE_PTR(policy_digest);
1916
1917 return 0;
1918}
1919
aff853f8 1920int tpm2_create_primary(
e3f1f210 1921 Tpm2Context *c,
aff853f8
DS
1922 const Tpm2Handle *session,
1923 const TPM2B_PUBLIC *template,
1924 const TPM2B_SENSITIVE_CREATE *sensitive,
1925 TPM2B_PUBLIC **ret_public,
1926 Tpm2Handle **ret_handle) {
1927
1928 usec_t ts;
1929 TSS2_RC rc;
1930 int r;
1931
1932 assert(c);
1933 assert(template);
1934
1935 log_debug("Creating primary key on TPM.");
1936
1937 ts = now(CLOCK_MONOTONIC);
1938
1939 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1940 r = tpm2_handle_new(c, &handle);
1941 if (r < 0)
1942 return r;
1943
1944 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
1945 rc = sym_Esys_CreatePrimary(
1946 c->esys_context,
1947 ESYS_TR_RH_OWNER,
1948 session ? session->esys_handle : ESYS_TR_PASSWORD,
1949 ESYS_TR_NONE,
1950 ESYS_TR_NONE,
1951 sensitive ? sensitive : &(TPM2B_SENSITIVE_CREATE) {},
1952 template,
1953 /* outsideInfo= */ NULL,
1954 &(TPML_PCR_SELECTION) {},
1955 &handle->esys_handle,
1956 &public,
1957 /* creationData= */ NULL,
1958 /* creationHash= */ NULL,
1959 /* creationTicket= */ NULL);
1960 if (rc != TSS2_RC_SUCCESS)
1961 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1962 "Failed to generate primary key in TPM: %s",
1963 sym_Tss2_RC_Decode(rc));
1964
1965 log_debug("Successfully created primary key on TPM in %s.",
1966 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
1967
1968 if (ret_public)
1969 *ret_public = TAKE_PTR(public);
1970 if (ret_handle)
1971 *ret_handle = TAKE_PTR(handle);
1972
1973 return 0;
1974}
1975
1976/* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
1977 * instead use tpm2_create_primary(). */
1978int tpm2_create(Tpm2Context *c,
e3f1f210
DS
1979 const Tpm2Handle *parent,
1980 const Tpm2Handle *session,
1981 const TPMT_PUBLIC *template,
1982 const TPMS_SENSITIVE_CREATE *sensitive,
1983 TPM2B_PUBLIC **ret_public,
1984 TPM2B_PRIVATE **ret_private) {
1985
1986 usec_t ts;
1987 TSS2_RC rc;
1988
1989 assert(c);
aff853f8 1990 assert(parent);
e3f1f210
DS
1991 assert(template);
1992
1993 log_debug("Creating object on TPM.");
1994
1995 ts = now(CLOCK_MONOTONIC);
1996
1997 TPM2B_PUBLIC tpm2b_public = {
1998 .size = sizeof(*template) - sizeof(template->unique),
1999 .publicArea = *template,
2000 };
2001
2002 /* Zero the unique area. */
2003 zero(tpm2b_public.publicArea.unique);
2004
2005 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2006 if (sensitive)
2007 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2008 .size = sizeof(*sensitive),
2009 .sensitive = *sensitive,
2010 };
2011 else
2012 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2013
2014 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2015 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2016 rc = sym_Esys_Create(
2017 c->esys_context,
aff853f8 2018 parent->esys_handle,
e3f1f210
DS
2019 session ? session->esys_handle : ESYS_TR_PASSWORD,
2020 ESYS_TR_NONE,
2021 ESYS_TR_NONE,
2022 &tpm2b_sensitive,
2023 &tpm2b_public,
2024 /* outsideInfo= */ NULL,
2025 &(TPML_PCR_SELECTION) {},
2026 &private,
2027 &public,
2028 /* creationData= */ NULL,
2029 /* creationHash= */ NULL,
2030 /* creationTicket= */ NULL);
2031 if (rc != TSS2_RC_SUCCESS)
2032 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2033 "Failed to generate object in TPM: %s",
2034 sym_Tss2_RC_Decode(rc));
2035
2036 log_debug("Successfully created object on TPM in %s.",
2037 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2038
2039 if (ret_public)
2040 *ret_public = TAKE_PTR(public);
2041 if (ret_private)
2042 *ret_private = TAKE_PTR(private);
2043
2044 return 0;
2045}
2046
d1d0de73
DS
2047static int tpm2_load(
2048 Tpm2Context *c,
2049 const Tpm2Handle *parent,
2050 const Tpm2Handle *session,
2051 const TPM2B_PUBLIC *public,
2052 const TPM2B_PRIVATE *private,
2053 Tpm2Handle **ret_handle) {
2054
2055 TSS2_RC rc;
2056 int r;
2057
2058 assert(c);
2059 assert(public);
2060 assert(private);
2061 assert(ret_handle);
2062
2063 log_debug("Loading object into TPM.");
2064
2065 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2066 r = tpm2_handle_new(c, &handle);
2067 if (r < 0)
2068 return r;
2069
2070 rc = sym_Esys_Load(
2071 c->esys_context,
2072 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
2073 session ? session->esys_handle : ESYS_TR_PASSWORD,
2074 ESYS_TR_NONE,
2075 ESYS_TR_NONE,
2076 private,
2077 public,
2078 &handle->esys_handle);
2079 if (rc == TPM2_RC_LOCKOUT)
2080 return log_error_errno(SYNTHETIC_ERRNO(ENOLCK),
2081 "TPM2 device is in dictionary attack lockout mode.");
2082 if (rc != TSS2_RC_SUCCESS)
2083 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2084 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc));
2085
2086 *ret_handle = TAKE_PTR(handle);
2087
2088 return 0;
2089}
2090
efe153bd
DS
2091static int tpm2_load_external(
2092 Tpm2Context *c,
2093 const Tpm2Handle *session,
2094 const TPM2B_PUBLIC *public,
2095 const TPM2B_SENSITIVE *private,
2096 Tpm2Handle **ret_handle) {
2097
2098 TSS2_RC rc;
2099 int r;
2100
2101 assert(c);
2102 assert(ret_handle);
2103
2104 log_debug("Loading external key into TPM.");
2105
2106 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2107 r = tpm2_handle_new(c, &handle);
2108 if (r < 0)
2109 return r;
2110
2111 rc = sym_Esys_LoadExternal(
2112 c->esys_context,
2113 session ? session->esys_handle : ESYS_TR_NONE,
2114 ESYS_TR_NONE,
2115 ESYS_TR_NONE,
2116 private,
2117 public,
2118#if HAVE_TSS2_ESYS3
2119 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2120 * hierarchy, older versions need TPM2_RH_* instead. */
2121 ESYS_TR_RH_OWNER,
2122#else
2123 TPM2_RH_OWNER,
2124#endif
2125 &handle->esys_handle);
2126 if (rc != TSS2_RC_SUCCESS)
2127 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2128 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
2129
2130 *ret_handle = TAKE_PTR(handle);
2131
2132 return 0;
2133}
2134
cea525a9
DS
2135/* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2136 * use tpm2_create_loaded(). */
2137static int _tpm2_create_loaded(
2138 Tpm2Context *c,
2139 const Tpm2Handle *parent,
2140 const Tpm2Handle *session,
2141 const TPMT_PUBLIC *template,
2142 const TPMS_SENSITIVE_CREATE *sensitive,
2143 TPM2B_PUBLIC **ret_public,
2144 TPM2B_PRIVATE **ret_private,
2145 Tpm2Handle **ret_handle) {
2146
2147 usec_t ts;
2148 TSS2_RC rc;
2149 int r;
2150
2151 assert(c);
aff853f8 2152 assert(parent);
cea525a9
DS
2153 assert(template);
2154
2155 log_debug("Creating loaded object on TPM.");
2156
2157 ts = now(CLOCK_MONOTONIC);
2158
2159 /* Copy the input template and zero the unique area. */
2160 TPMT_PUBLIC template_copy = *template;
2161 zero(template_copy.unique);
2162
2163 TPM2B_TEMPLATE tpm2b_template;
2164 size_t size = 0;
2165 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2166 &template_copy,
2167 tpm2b_template.buffer,
2168 sizeof(tpm2b_template.buffer),
2169 &size);
2170 if (rc != TSS2_RC_SUCCESS)
2171 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2172 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc));
2173 assert(size <= UINT16_MAX);
2174 tpm2b_template.size = size;
2175
2176 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2177 if (sensitive)
2178 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2179 .size = sizeof(*sensitive),
2180 .sensitive = *sensitive,
2181 };
2182 else
2183 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2184
2185 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2186 r = tpm2_handle_new(c, &handle);
2187 if (r < 0)
2188 return r;
2189
2190 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2191 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2192 rc = sym_Esys_CreateLoaded(
2193 c->esys_context,
aff853f8 2194 parent->esys_handle,
cea525a9
DS
2195 session ? session->esys_handle : ESYS_TR_PASSWORD,
2196 ESYS_TR_NONE,
2197 ESYS_TR_NONE,
2198 &tpm2b_sensitive,
2199 &tpm2b_template,
2200 &handle->esys_handle,
2201 &private,
2202 &public);
2203 if (rc != TSS2_RC_SUCCESS)
2204 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2205 "Failed to generate loaded object in TPM: %s",
2206 sym_Tss2_RC_Decode(rc));
2207
2208 log_debug("Successfully created loaded object on TPM in %s.",
2209 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2210
2211 if (ret_public)
2212 *ret_public = TAKE_PTR(public);
2213 if (ret_private)
2214 *ret_private = TAKE_PTR(private);
2215 if (ret_handle)
2216 *ret_handle = TAKE_PTR(handle);
2217
2218 return 0;
2219}
2220
2221/* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
aff853f8
DS
2222 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2223 * tpm2_create_primary(). */
2224int tpm2_create_loaded(
cea525a9
DS
2225 Tpm2Context *c,
2226 const Tpm2Handle *parent,
2227 const Tpm2Handle *session,
2228 const TPMT_PUBLIC *template,
2229 const TPMS_SENSITIVE_CREATE *sensitive,
2230 TPM2B_PUBLIC **ret_public,
2231 TPM2B_PRIVATE **ret_private,
2232 Tpm2Handle **ret_handle) {
2233
2234 int r;
2235
2236 if (tpm2_supports_command(c, TPM2_CC_CreateLoaded))
2237 return _tpm2_create_loaded(c, parent, session, template, sensitive, ret_public, ret_private, ret_handle);
2238
2239 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2240 * create and load manually. */
2241 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2242 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2243 r = tpm2_create(c, parent, session, template, sensitive, &public, &private);
2244 if (r < 0)
2245 return r;
2246
2247 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2248 r = tpm2_load(c, parent, session, public, private, &handle);
2249 if (r < 0)
2250 return r;
2251
2252 if (ret_public)
2253 *ret_public = TAKE_PTR(public);
2254 if (ret_private)
2255 *ret_private = TAKE_PTR(private);
2256 if (ret_handle)
2257 *ret_handle = TAKE_PTR(handle);
2258
2259 return 0;
2260}
2261
323eb480
DS
2262/* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2263 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2264 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2265 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2266 * values. */
b4a6fcd5 2267int tpm2_pcr_read(
c57d8bc8
DS
2268 Tpm2Context *c,
2269 const TPML_PCR_SELECTION *pcr_selection,
323eb480 2270 Tpm2PCRValue **ret_pcr_values,
c648a4b8 2271 size_t *ret_n_pcr_values) {
c57d8bc8 2272
323eb480 2273 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
c648a4b8 2274 size_t n_pcr_values = 0;
c57d8bc8 2275 TSS2_RC rc;
321a9d9e 2276
c57d8bc8
DS
2277 assert(c);
2278 assert(pcr_selection);
323eb480
DS
2279 assert(ret_pcr_values);
2280 assert(ret_n_pcr_values);
321a9d9e 2281
323eb480 2282 TPML_PCR_SELECTION remaining = *pcr_selection;
c57d8bc8
DS
2283 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
2284 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
2285 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
321a9d9e 2286
c57d8bc8 2287 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
321a9d9e 2288
c57d8bc8
DS
2289 /* Unfortunately, PCR_Read will not return more than 8 values. */
2290 rc = sym_Esys_PCR_Read(
2291 c->esys_context,
2292 ESYS_TR_NONE,
2293 ESYS_TR_NONE,
2294 ESYS_TR_NONE,
2295 &remaining,
2296 NULL,
2297 &current_read,
2298 &current_values);
2299 if (rc != TSS2_RC_SUCCESS)
2300 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2301 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
321a9d9e 2302
323eb480
DS
2303 tpm2_log_debug_tpml_pcr_selection(current_read, "Read PCR selection");
2304
c57d8bc8
DS
2305 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
2306 log_warning("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2307 break;
321a9d9e
LP
2308 }
2309
323eb480
DS
2310 unsigned i = 0;
2311 FOREACH_PCR_IN_TPML_PCR_SELECTION(index, tpms, current_read) {
2312 assert(i < current_values->count);
2313 Tpm2PCRValue pcr_value = {
2314 .index = index,
2315 .hash = tpms->hash,
2316 .value = current_values->digests[i++],
2317 };
c57d8bc8 2318
323eb480 2319 tpm2_log_debug_pcr_value(&pcr_value, /* msg= */ NULL);
c57d8bc8 2320
323eb480
DS
2321 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
2322 return log_oom();
2323 }
2324 assert(i == current_values->count);
c57d8bc8 2325
323eb480
DS
2326 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
2327 }
c57d8bc8 2328
323eb480 2329 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
c57d8bc8 2330
cc1a78d5 2331 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
323eb480 2332 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PCR values read from TPM are not valid.");
321a9d9e 2333
323eb480
DS
2334 *ret_pcr_values = TAKE_PTR(pcr_values);
2335 *ret_n_pcr_values = n_pcr_values;
c57d8bc8
DS
2336
2337 return 0;
321a9d9e
LP
2338}
2339
b4a6fcd5
DS
2340/* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2341 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2342 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2343 * appropriate entries, this returns an error. This does not check the array for validity. */
2344int tpm2_pcr_read_missing_values(Tpm2Context *c, Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
2345 TPMI_ALG_HASH pcr_bank = 0;
2346 int r;
2347
2348 assert(c);
2349 assert(pcr_values || n_pcr_values == 0);
2350
2351 if (n_pcr_values > 0) {
2352 size_t hash_count;
2353 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
2354 if (r < 0)
2355 return log_error_errno(r, "Could not get hash count from pcr values: %m");
2356
2357 if (hash_count == 1 && pcr_values[0].hash == 0) {
2358 uint32_t mask;
2359 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, 0, &mask);
2360 if (r < 0)
2361 return r;
2362
2363 r = tpm2_get_best_pcr_bank(c, mask, &pcr_bank);
2364 if (r < 0)
2365 return r;
2366 }
2367 }
2368
193fd573 2369 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
b4a6fcd5
DS
2370 if (v->hash == 0)
2371 v->hash = pcr_bank;
2372
2373 if (v->value.size > 0)
2374 continue;
2375
2376 TPML_PCR_SELECTION selection;
2377 r = tpm2_tpml_pcr_selection_from_pcr_values(v, 1, &selection, NULL, NULL);
2378 if (r < 0)
2379 return r;
2380
2381 _cleanup_free_ Tpm2PCRValue *read_values = NULL;
2382 size_t n_read_values;
2383 r = tpm2_pcr_read(c, &selection, &read_values, &n_read_values);
2384 if (r < 0)
2385 return r;
2386
2387 if (n_read_values == 0)
2388 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2389 "Could not read PCR hash 0x%" PRIu16 " index %u",
2390 v->hash, v->index);
2391
2392 assert(n_read_values == 1);
2393 assert(read_values[0].hash == v->hash);
2394 assert(read_values[0].index == v->index);
2395
2396 v->value = read_values[0].value;
2397 }
2398
2399 return 0;
2400}
2401
321a9d9e 2402static int tpm2_pcr_mask_good(
23e9ccc2 2403 Tpm2Context *c,
321a9d9e
LP
2404 TPMI_ALG_HASH bank,
2405 uint32_t mask) {
2406
321a9d9e 2407 TPML_PCR_SELECTION selection;
c57d8bc8 2408 int r;
321a9d9e
LP
2409
2410 assert(c);
2411
2412 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2413 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2414 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2415
c69bd0ab 2416 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
321a9d9e 2417
323eb480
DS
2418 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2419 size_t n_pcr_values;
2420 r = tpm2_pcr_read(c, &selection, &pcr_values, &n_pcr_values);
c57d8bc8
DS
2421 if (r < 0)
2422 return r;
321a9d9e
LP
2423
2424 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
193fd573
DS
2425 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
2426 if (!memeqbyte(0x00, v->value.buffer, v->value.size) &&
2427 !memeqbyte(0xFF, v->value.buffer, v->value.size))
c57d8bc8 2428 return true;
321a9d9e 2429
c57d8bc8 2430 return false;
321a9d9e
LP
2431}
2432
59fafaee
LP
2433static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
2434
2435 assert(selection);
2436
2437 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2438 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2439 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
2440 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
7bfe0a48 2441 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
2442 return false;
2443 }
2444
2445 assert_cc(TPM2_PCRS_MAX % 8 == 0);
2446
2447 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2448 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2449 bool valid = true;
2450 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
2451 if (selection->pcrSelect[j] != 0xFF) {
2452 valid = false;
2453 break;
2454 }
2455
2456 if (!valid)
2457 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
7bfe0a48 2458 strna(tpm2_hash_alg_to_string(selection->hash)));
59fafaee
LP
2459
2460 return valid;
2461}
2462
b4a6fcd5 2463int tpm2_get_best_pcr_bank(
23e9ccc2 2464 Tpm2Context *c,
321a9d9e 2465 uint32_t pcr_mask,
07697bfe
LP
2466 TPMI_ALG_HASH *ret) {
2467
321a9d9e 2468 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
59fafaee 2469 int r;
07697bfe 2470
321a9d9e 2471 assert(c);
3a35d6cd 2472 assert(ret);
321a9d9e 2473
9ea0ffe6 2474 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
3a35d6cd 2475 TPMI_ALG_HASH hash = selection->hash;
321a9d9e
LP
2476 int good;
2477
2478 /* For now we are only interested in the SHA1 and SHA256 banks */
3a35d6cd 2479 if (!IN_SET(hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
321a9d9e 2480 continue;
07697bfe 2481
3a35d6cd 2482 r = tpm2_bank_has24(selection);
59fafaee
LP
2483 if (r < 0)
2484 return r;
2485 if (!r)
07697bfe 2486 continue;
07697bfe 2487
3a35d6cd 2488 good = tpm2_pcr_mask_good(c, hash, pcr_mask);
321a9d9e
LP
2489 if (good < 0)
2490 return good;
2491
3a35d6cd 2492 if (hash == TPM2_ALG_SHA256) {
321a9d9e
LP
2493 supported_hash = TPM2_ALG_SHA256;
2494 if (good) {
2495 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2496 hash_with_valid_pcr = TPM2_ALG_SHA256;
2497 break;
2498 }
2499 } else {
3a35d6cd 2500 assert(hash == TPM2_ALG_SHA1);
321a9d9e
LP
2501
2502 if (supported_hash == 0)
2503 supported_hash = TPM2_ALG_SHA1;
07697bfe 2504
321a9d9e
LP
2505 if (good && hash_with_valid_pcr == 0)
2506 hash_with_valid_pcr = TPM2_ALG_SHA1;
2507 }
07697bfe
LP
2508 }
2509
321a9d9e
LP
2510 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2511 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2512 * SHA1.
2513 *
2514 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2515 * not initialized. */
2516
2517 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
2518 assert(supported_hash == TPM2_ALG_SHA256);
2519 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2520 *ret = TPM2_ALG_SHA256;
2521 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
2522 if (supported_hash == TPM2_ALG_SHA256)
2523 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.");
2524 else {
2525 assert(supported_hash == TPM2_ALG_SHA1);
2526 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.");
2527 }
2528
2529 *ret = TPM2_ALG_SHA1;
2530 } else if (supported_hash == TPM2_ALG_SHA256) {
2531 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!");
2532 *ret = TPM2_ALG_SHA256;
2533 } else if (supported_hash == TPM2_ALG_SHA1) {
2534 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!");
2535 *ret = TPM2_ALG_SHA1;
2536 } else
07697bfe
LP
2537 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2538 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2539
07697bfe
LP
2540 return 0;
2541}
2542
c5bf1f85 2543int tpm2_get_good_pcr_banks(
23e9ccc2 2544 Tpm2Context *c,
c5bf1f85
LP
2545 uint32_t pcr_mask,
2546 TPMI_ALG_HASH **ret) {
2547
2548 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
c5bf1f85 2549 size_t n_good_banks = 0, n_fallback_banks = 0;
c5bf1f85
LP
2550 int r;
2551
2552 assert(c);
2553 assert(ret);
2554
9ea0ffe6 2555 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
3a35d6cd 2556 TPMI_ALG_HASH hash = selection->hash;
c5bf1f85
LP
2557
2558 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
3a35d6cd 2559 r = tpm2_bank_has24(selection);
c5bf1f85
LP
2560 if (r < 0)
2561 return r;
2562 if (!r)
2563 continue;
2564
2565 /* Let's now see if this bank has any of the selected PCRs actually initialized */
3a35d6cd 2566 r = tpm2_pcr_mask_good(c, hash, pcr_mask);
c5bf1f85
LP
2567 if (r < 0)
2568 return r;
2569
2570 if (n_good_banks + n_fallback_banks >= INT_MAX)
2571 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
2572
2573 if (r) {
2574 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
2575 return log_oom();
2576
3a35d6cd 2577 good_banks[n_good_banks++] = hash;
c5bf1f85
LP
2578 } else {
2579 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
2580 return log_oom();
2581
3a35d6cd 2582 fallback_banks[n_fallback_banks++] = hash;
c5bf1f85
LP
2583 }
2584 }
2585
2586 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2587 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2588 if (n_good_banks > 0) {
2589 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
2590 *ret = TAKE_PTR(good_banks);
2591 return (int) n_good_banks;
2592 }
2593 if (n_fallback_banks > 0) {
2594 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
2595 *ret = TAKE_PTR(fallback_banks);
2596 return (int) n_fallback_banks;
2597 }
2598
2599 /* No suitable banks found. */
2600 *ret = NULL;
2601 return 0;
2602}
2603
e4481cc5 2604int tpm2_get_good_pcr_banks_strv(
23e9ccc2 2605 Tpm2Context *c,
e4481cc5
LP
2606 uint32_t pcr_mask,
2607 char ***ret) {
2608
0d7009d3 2609#if HAVE_OPENSSL
e4481cc5
LP
2610 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
2611 _cleanup_strv_free_ char **l = NULL;
2612 int n_algs;
2613
2614 assert(c);
2615 assert(ret);
2616
2617 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
2618 if (n_algs < 0)
2619 return n_algs;
2620
193fd573 2621 FOREACH_ARRAY(a, algs, n_algs) {
e4481cc5
LP
2622 _cleanup_free_ char *n = NULL;
2623 const EVP_MD *implementation;
2624 const char *salg;
2625
193fd573 2626 salg = tpm2_hash_alg_to_string(*a);
e4481cc5
LP
2627 if (!salg)
2628 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
2629
2630 implementation = EVP_get_digestbyname(salg);
2631 if (!implementation)
2632 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2633
2634 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
2635 if (!n)
2636 return log_oom();
2637
2638 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2639
2640 if (strv_consume(&l, TAKE_PTR(n)) < 0)
2641 return log_oom();
2642 }
2643
2644 *ret = TAKE_PTR(l);
2645 return 0;
0d7009d3
DS
2646#else /* HAVE_OPENSSL */
2647 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2648#endif
e4481cc5
LP
2649}
2650
da92d39a
DS
2651/* Hash data into the digest.
2652 *
2653 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2654 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2655 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2656 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2657 *
2658 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2659 * correct for 'alg'.
2660 *
2661 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2662int tpm2_digest_many(
2663 TPMI_ALG_HASH alg,
2664 TPM2B_DIGEST *digest,
2665 const struct iovec data[],
2666 size_t n_data,
2667 bool extend) {
2668
2669 struct sha256_ctx ctx;
2670
2671 assert(digest);
2672 assert(data || n_data == 0);
2673
2674 if (alg != TPM2_ALG_SHA256)
2675 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2676 "Hash algorithm not supported: 0x%x", alg);
2677
2678 if (extend && digest->size != SHA256_DIGEST_SIZE)
2679 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2680 "Digest size 0x%x, require 0x%x",
2681 digest->size, (unsigned)SHA256_DIGEST_SIZE);
2682
2683 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2684 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
2685
2686 CLEANUP_ERASE(ctx);
2687
2688 sha256_init_ctx(&ctx);
2689
2690 if (extend)
2691 sha256_process_bytes(digest->buffer, digest->size, &ctx);
2692 else {
2693 *digest = (TPM2B_DIGEST){ .size = SHA256_DIGEST_SIZE, };
2694 if (n_data == 0) /* If not extending and no data, return zero hash */
2695 return 0;
2696 }
2697
193fd573
DS
2698 FOREACH_ARRAY(d, data, n_data)
2699 sha256_process_bytes(d->iov_base, d->iov_len, &ctx);
da92d39a
DS
2700
2701 sha256_finish_ctx(&ctx, digest->buffer);
2702
2703 return 0;
2704}
2705
2706/* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
2707int tpm2_digest_many_digests(
2708 TPMI_ALG_HASH alg,
2709 TPM2B_DIGEST *digest,
2710 const TPM2B_DIGEST data[],
2711 size_t n_data,
2712 bool extend) {
2713
2714 _cleanup_free_ struct iovec *iovecs = NULL;
2715
2716 assert(data || n_data == 0);
2717
2718 iovecs = new(struct iovec, n_data);
2719 if (!iovecs)
2720 return log_oom();
2721
2722 for (size_t i = 0; i < n_data; i++)
2723 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
2724
2725 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
2726}
2727
f230572f
DS
2728/* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
2729 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
2730 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
2731 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
63477a71
DS
2732 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2733 *
2734 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2735 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2736 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2737 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2738 *
2739 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2740 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2741 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2742 *
2743 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2744 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2745 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2746 * which we will trim the 0(s) from before sending to the TPM.
2747 */
2748static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
2749 bool trimmed = false;
2750
2751 assert(auth);
2752
2753 while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
2754 trimmed = true;
2755 auth->size--;
2756 }
2757
2758 if (trimmed)
2759 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2760}
2761
f230572f
DS
2762static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
2763 TPM2B_AUTH auth = {};
2764 int r;
2765
2766 assert(pin);
2767 assert(ret_auth);
2768
2769 r = tpm2_digest_buffer(hash, &auth, pin, strlen(pin), /* extend= */ false);
2770 if (r < 0)
2771 return r;
2772
63477a71 2773 tpm2_trim_auth_value(&auth);
f230572f
DS
2774
2775 *ret_auth = TAKE_STRUCT(auth);
2776
2777 return 0;
2778}
2779
409a65f8
DS
2780static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
2781 TPM2B_AUTH auth = {};
2782 TSS2_RC rc;
2783 int r;
2784
2785 assert(c);
2786 assert(handle);
2787
2788 if (!pin)
2789 return 0;
2790
2791 CLEANUP_ERASE(auth);
2792
f230572f 2793 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &auth);
409a65f8
DS
2794 if (r < 0)
2795 return r;
2796
2797 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, &auth);
2798 if (rc != TSS2_RC_SUCCESS)
2799 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2800 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
2801
2802 return 0;
2803}
2804
e976445d
DS
2805static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
2806 TPMA_SESSION flags = 0;
2807 TSS2_RC rc;
2808
2809 assert(c);
2810 assert(session);
2811
2812 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
2813 if (rc != TSS2_RC_SUCCESS)
2814 return false;
2815
2816 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
2817}
2818
da29de23 2819static int tpm2_make_encryption_session(
23e9ccc2 2820 Tpm2Context *c,
16e16b8c
DS
2821 const Tpm2Handle *primary,
2822 const Tpm2Handle *bind_key,
16e16b8c 2823 Tpm2Handle **ret_session) {
da29de23 2824
da29de23
GG
2825 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
2826 TPMA_SESSION_CONTINUESESSION;
da29de23 2827 TSS2_RC rc;
16e16b8c 2828 int r;
da29de23
GG
2829
2830 assert(c);
16e16b8c 2831 assert(ret_session);
da29de23
GG
2832
2833 log_debug("Starting HMAC encryption session.");
2834
2835 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
2836 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
2837 * recover the salt, which is then used for key derivation. */
1dc8f518 2838 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
16e16b8c
DS
2839 r = tpm2_handle_new(c, &session);
2840 if (r < 0)
2841 return r;
2842
da29de23 2843 rc = sym_Esys_StartAuthSession(
23e9ccc2 2844 c->esys_context,
16e16b8c
DS
2845 primary->esys_handle,
2846 bind_key->esys_handle,
da29de23
GG
2847 ESYS_TR_NONE,
2848 ESYS_TR_NONE,
2849 ESYS_TR_NONE,
2850 NULL,
2851 TPM2_SE_HMAC,
a47060bb 2852 &SESSION_TEMPLATE_SYM_AES_128_CFB,
da29de23 2853 TPM2_ALG_SHA256,
16e16b8c 2854 &session->esys_handle);
da29de23
GG
2855 if (rc != TSS2_RC_SUCCESS)
2856 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2857 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2858
2859 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
2860 * always used for sessions), this provides confidentiality, integrity and replay protection for
2861 * operations that use this session. */
16e16b8c 2862 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
da29de23
GG
2863 if (rc != TSS2_RC_SUCCESS)
2864 return log_error_errno(
2865 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2866 "Failed to configure TPM session: %s",
2867 sym_Tss2_RC_Decode(rc));
2868
16e16b8c 2869 *ret_session = TAKE_PTR(session);
da29de23 2870
da29de23
GG
2871 return 0;
2872}
2873
2cd9d575
DS
2874static int tpm2_make_policy_session(
2875 Tpm2Context *c,
2876 const Tpm2Handle *primary,
2877 const Tpm2Handle *encryption_session,
2878 bool trial,
2879 Tpm2Handle **ret_session) {
2880
2cd9d575
DS
2881 TPM2_SE session_type = trial ? TPM2_SE_TRIAL : TPM2_SE_POLICY;
2882 TSS2_RC rc;
2883 int r;
2884
2885 assert(c);
2886 assert(primary);
2887 assert(encryption_session);
2888 assert(ret_session);
2889
2890 if (!tpm2_is_encryption_session(c, encryption_session))
2891 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2892 "Missing encryption session");
2893
2894 log_debug("Starting policy session.");
2895
1dc8f518 2896 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
2cd9d575
DS
2897 r = tpm2_handle_new(c, &session);
2898 if (r < 0)
2899 return r;
2900
2901 rc = sym_Esys_StartAuthSession(
2902 c->esys_context,
2903 primary->esys_handle,
2904 ESYS_TR_NONE,
2905 encryption_session->esys_handle,
2906 ESYS_TR_NONE,
2907 ESYS_TR_NONE,
2908 NULL,
2909 session_type,
a47060bb 2910 &SESSION_TEMPLATE_SYM_AES_128_CFB,
2cd9d575
DS
2911 TPM2_ALG_SHA256,
2912 &session->esys_handle);
2913 if (rc != TSS2_RC_SUCCESS)
2914 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2915 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
2916
2917 *ret_session = TAKE_PTR(session);
2918
2919 return 0;
2920}
2921
d9b5841d
LP
2922static int find_signature(
2923 JsonVariant *v,
95898241
DS
2924 const TPML_PCR_SELECTION *pcr_selection,
2925 const void *fp,
2926 size_t fp_size,
d9b5841d
LP
2927 const void *policy,
2928 size_t policy_size,
2929 void *ret_signature,
2930 size_t *ret_signature_size) {
2931
95898241 2932#if HAVE_OPENSSL
d9b5841d 2933 JsonVariant *b, *i;
d9b5841d
LP
2934 const char *k;
2935 int r;
2936
2937 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
2938 * public key, and policy digest. */
2939
2940 if (!json_variant_is_object(v))
2941 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
2942
95898241 2943 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
dbaae766 2944 uint32_t pcr_mask = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank);
95898241 2945
7bfe0a48 2946 k = tpm2_hash_alg_to_string(pcr_bank);
d9b5841d
LP
2947 if (!k)
2948 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
2949
2950 /* First, find field by bank */
2951 b = json_variant_by_key(v, k);
2952 if (!b)
2953 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
2954
2955 if (!json_variant_is_array(b))
2956 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
2957
2958 /* Now iterate through all signatures known for this bank */
2959 JSON_VARIANT_ARRAY_FOREACH(i, b) {
2960 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
2961 JsonVariant *maskj, *fpj, *sigj, *polj;
2962 size_t fpj_size, polj_size;
2963 uint32_t parsed_mask;
2964
2965 if (!json_variant_is_object(i))
2966 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
2967
2968 /* Check if the PCR mask matches our expectations */
2969 maskj = json_variant_by_key(i, "pcrs");
2970 if (!maskj)
2971 continue;
2972
2973 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
2974 if (r < 0)
2975 return log_error_errno(r, "Failed to parse JSON PCR mask");
2976
2977 if (parsed_mask != pcr_mask)
2978 continue; /* Not for this PCR mask */
2979
2980 /* Then check if this is for the public key we operate with */
2981 fpj = json_variant_by_key(i, "pkfp");
2982 if (!fpj)
2983 continue;
2984
2985 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
2986 if (r < 0)
2987 return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
2988
d9b5841d
LP
2989 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
2990 continue; /* Not for this public key */
2991
2992 /* Finally, check if this is for the PCR policy we expect this to be */
2993 polj = json_variant_by_key(i, "pol");
2994 if (!polj)
2995 continue;
2996
2997 r = json_variant_unhex(polj, &polj_data, &polj_size);
2998 if (r < 0)
2999 return log_error_errno(r, "Failed to decode policy hash JSON data: %m");
3000
3001 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
3002 continue;
3003
3004 /* This entry matches all our expectations, now return the signature included in it */
3005 sigj = json_variant_by_key(i, "sig");
3006 if (!sigj)
3007 continue;
3008
3009 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
3010 }
3011
3012 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
95898241
DS
3013#else /* HAVE_OPENSSL */
3014 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
395c1d9a 3015#endif
95898241 3016}
d9b5841d 3017
dbae4b95
DS
3018/* Calculates the "name" of a public key.
3019 *
3020 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3021 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3022 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3023 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3024 * that would also change the key name.
3025 *
3026 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3027 * nameAlg is not TPM2_ALG_SHA256. */
3028int tpm2_calculate_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
3029 TSS2_RC rc;
3030 int r;
3031
3032 assert(public);
3033 assert(ret_name);
3034
3035 r = dlopen_tpm2();
3036 if (r < 0)
3037 return log_error_errno(r, "TPM2 support not installed: %m");
3038
3039 if (public->nameAlg != TPM2_ALG_SHA256)
3040 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3041 "Unsupported nameAlg: 0x%x",
3042 public->nameAlg);
3043
3044 _cleanup_free_ uint8_t *buf = NULL;
3045 size_t size = 0;
3046
3047 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
3048 if (!buf)
3049 return log_oom();
3050
3051 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
3052 if (rc != TSS2_RC_SUCCESS)
3053 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3054 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
3055
3056 TPM2B_DIGEST digest = {};
3057 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3058 if (r < 0)
3059 return r;
3060
3061 TPMT_HA ha = {
3062 .hashAlg = TPM2_ALG_SHA256,
3063 };
3064 assert(digest.size <= sizeof(ha.digest.sha256));
3065 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3066
3067 TPM2B_NAME name;
3068 size = 0;
3069 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3070 if (rc != TSS2_RC_SUCCESS)
3071 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3072 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
3073 name.size = size;
3074
3075 tpm2_log_debug_name(&name, "Calculated name");
3076
3077 *ret_name = name;
3078
3079 return 0;
3080}
3081
3082/* Get the "name" of a key from the TPM.
3083 *
3084 * The "name" of a key is explained above in tpm2_calculate_name().
3085 *
3086 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3087 * public/private keypair. */
3088static int tpm2_get_name(
3089 Tpm2Context *c,
3090 const Tpm2Handle *handle,
3091 TPM2B_NAME **ret_name) {
3092
3093 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
3094 TSS2_RC rc;
3095
3096 assert(c);
3097 assert(handle);
3098 assert(ret_name);
3099
3100 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
3101 if (rc != TSS2_RC_SUCCESS)
3102 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3103 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
3104
3105 tpm2_log_debug_name(name, "Object name");
3106
3107 *ret_name = TAKE_PTR(name);
3108
3109 return 0;
3110}
3111
8a716354
DS
3112/* Extend 'digest' with the PolicyAuthValue calculated hash. */
3113int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
3114 TPM2_CC command = TPM2_CC_PolicyAuthValue;
3115 TSS2_RC rc;
3116 int r;
3117
3118 assert(digest);
3119 assert(digest->size == SHA256_DIGEST_SIZE);
3120
3121 r = dlopen_tpm2();
3122 if (r < 0)
3123 return log_error_errno(r, "TPM2 support not installed: %m");
3124
3125 uint8_t buf[sizeof(command)];
3126 size_t offset = 0;
3127
3128 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3129 if (rc != TSS2_RC_SUCCESS)
3130 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3131 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
3132
3133 if (offset != sizeof(command))
3134 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3135 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
3136
3137 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
3138 if (r < 0)
3139 return r;
3140
3141 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
3142
3143 return 0;
3144}
3145
3146static int tpm2_policy_auth_value(
3147 Tpm2Context *c,
3148 const Tpm2Handle *session,
3149 TPM2B_DIGEST **ret_policy_digest) {
3150
3151 TSS2_RC rc;
3152
3153 assert(c);
3154 assert(session);
3155
3156 log_debug("Adding authValue policy.");
3157
3158 rc = sym_Esys_PolicyAuthValue(
3159 c->esys_context,
3160 session->esys_handle,
3161 ESYS_TR_NONE,
3162 ESYS_TR_NONE,
3163 ESYS_TR_NONE);
3164 if (rc != TSS2_RC_SUCCESS)
3165 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3166 "Failed to add authValue policy to TPM: %s",
3167 sym_Tss2_RC_Decode(rc));
3168
3169 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3170}
3171
dcbc4674
DS
3172/* Extend 'digest' with the PolicyPCR calculated hash. */
3173int tpm2_calculate_policy_pcr(
6e8fb3ad 3174 const Tpm2PCRValue *pcr_values,
dcbc4674
DS
3175 size_t n_pcr_values,
3176 TPM2B_DIGEST *digest) {
3177
3178 TPM2_CC command = TPM2_CC_PolicyPCR;
3179 TSS2_RC rc;
3180 int r;
3181
dcbc4674
DS
3182 assert(pcr_values || n_pcr_values == 0);
3183 assert(digest);
3184 assert(digest->size == SHA256_DIGEST_SIZE);
3185
3186 r = dlopen_tpm2();
3187 if (r < 0)
3188 return log_error_errno(r, "TPM2 support not installed: %m");
3189
6e8fb3ad
DS
3190 TPML_PCR_SELECTION pcr_selection;
3191 _cleanup_free_ TPM2B_DIGEST *values = NULL;
3192 size_t n_values;
3193 r = tpm2_tpml_pcr_selection_from_pcr_values(pcr_values, n_pcr_values, &pcr_selection, &values, &n_values);
3194 if (r < 0)
3195 return log_error_errno(r, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3196
dcbc4674 3197 TPM2B_DIGEST hash = {};
6e8fb3ad 3198 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, values, n_values, /* extend= */ false);
dcbc4674
DS
3199 if (r < 0)
3200 return r;
3201
3202 _cleanup_free_ uint8_t *buf = NULL;
6e8fb3ad 3203 size_t size = 0, maxsize = sizeof(command) + sizeof(pcr_selection);
dcbc4674
DS
3204
3205 buf = malloc(maxsize);
3206 if (!buf)
3207 return log_oom();
3208
3209 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
3210 if (rc != TSS2_RC_SUCCESS)
3211 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3212 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
3213
6e8fb3ad 3214 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection, buf, maxsize, &size);
dcbc4674
DS
3215 if (rc != TSS2_RC_SUCCESS)
3216 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3217 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
3218
3219 struct iovec data[] = {
3220 IOVEC_MAKE(buf, size),
3221 IOVEC_MAKE(hash.buffer, hash.size),
3222 };
3223 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3224 if (r < 0)
3225 return r;
3226
3227 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
3228
3229 return 0;
3230}
3231
3232static int tpm2_policy_pcr(
3233 Tpm2Context *c,
3234 const Tpm2Handle *session,
3235 const TPML_PCR_SELECTION *pcr_selection,
3236 TPM2B_DIGEST **ret_policy_digest) {
3237
3238 TSS2_RC rc;
3239
3240 assert(c);
3241 assert(session);
3242 assert(pcr_selection);
3243
3244 log_debug("Adding PCR hash policy.");
3245
3246 rc = sym_Esys_PolicyPCR(
3247 c->esys_context,
3248 session->esys_handle,
3249 ESYS_TR_NONE,
3250 ESYS_TR_NONE,
3251 ESYS_TR_NONE,
3252 NULL,
3253 pcr_selection);
3254 if (rc != TSS2_RC_SUCCESS)
3255 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3256 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
3257
3258 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3259}
3260
5c7852f7
DS
3261/* Extend 'digest' with the PolicyAuthorize calculated hash. */
3262int tpm2_calculate_policy_authorize(
3263 const TPM2B_PUBLIC *public,
3264 const TPM2B_DIGEST *policy_ref,
3265 TPM2B_DIGEST *digest) {
3266
3267 TPM2_CC command = TPM2_CC_PolicyAuthorize;
3268 TSS2_RC rc;
3269 int r;
3270
3271 assert(public);
3272 assert(digest);
3273 assert(digest->size == SHA256_DIGEST_SIZE);
3274
3275 r = dlopen_tpm2();
3276 if (r < 0)
3277 return log_error_errno(r, "TPM2 support not installed: %m");
3278
3279 uint8_t buf[sizeof(command)];
3280 size_t offset = 0;
3281
3282 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3283 if (rc != TSS2_RC_SUCCESS)
3284 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3285 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
3286
3287 if (offset != sizeof(command))
3288 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3289 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
3290
3291 TPM2B_NAME name = {};
3292 r = tpm2_calculate_name(&public->publicArea, &name);
3293 if (r < 0)
3294 return r;
3295
3296 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3297 zero(digest->buffer);
3298
3299 struct iovec data[] = {
3300 IOVEC_MAKE(buf, offset),
3301 IOVEC_MAKE(name.name, name.size),
3302 };
3303 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3304 if (r < 0)
3305 return r;
3306
3307 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3308 if (policy_ref)
3309 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
3310 else
3311 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
3312 if (r < 0)
3313 return r;
3314
3315 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
3316
3317 return 0;
3318}
3319
3320static int tpm2_policy_authorize(
3321 Tpm2Context *c,
3322 const Tpm2Handle *session,
3323 TPML_PCR_SELECTION *pcr_selection,
3324 const TPM2B_PUBLIC *public,
3325 const void *fp,
3326 size_t fp_size,
3327 JsonVariant *signature_json,
3328 TPM2B_DIGEST **ret_policy_digest) {
3329
3330 TSS2_RC rc;
3331 int r;
3332
3333 assert(c);
3334 assert(session);
3335 assert(pcr_selection);
3336 assert(public);
3337 assert(fp && fp_size > 0);
3338
3339 log_debug("Adding PCR signature policy.");
3340
1dc8f518 3341 _cleanup_(tpm2_handle_freep) Tpm2Handle *pubkey_handle = NULL;
efe153bd 3342 r = tpm2_load_external(c, NULL, public, NULL, &pubkey_handle);
5c7852f7
DS
3343 if (r < 0)
3344 return r;
3345
5c7852f7
DS
3346 /* Acquire the "name" of what we just loaded */
3347 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
3348 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
3349 if (r < 0)
3350 return r;
3351
3352 /* If we have a signature, proceed with verifying the PCR digest */
3353 const TPMT_TK_VERIFIED *check_ticket;
3354 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
3355 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
3356 if (signature_json) {
3357 r = tpm2_policy_pcr(
3358 c,
3359 session,
3360 pcr_selection,
3361 &approved_policy);
3362 if (r < 0)
3363 return r;
3364
3365 _cleanup_free_ void *signature_raw = NULL;
3366 size_t signature_size;
3367
3368 r = find_signature(
3369 signature_json,
3370 pcr_selection,
3371 fp, fp_size,
3372 approved_policy->buffer,
3373 approved_policy->size,
3374 &signature_raw,
3375 &signature_size);
3376 if (r < 0)
3377 return r;
3378
3379 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3380 * hence we need to do the SHA256 part ourselves, first */
3381 TPM2B_DIGEST signature_hash = *approved_policy;
3382 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
3383 if (r < 0)
3384 return r;
3385
53b91e19
DS
3386 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size);
3387 if (r < 0)
3388 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
3389
5c7852f7
DS
3390 TPMT_SIGNATURE policy_signature = {
3391 .sigAlg = TPM2_ALG_RSASSA,
3392 .signature.rsassa = {
3393 .hash = TPM2_ALG_SHA256,
53b91e19 3394 .sig = TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw, signature_size),
5c7852f7
DS
3395 },
3396 };
5c7852f7
DS
3397
3398 rc = sym_Esys_VerifySignature(
3399 c->esys_context,
3400 pubkey_handle->esys_handle,
3401 ESYS_TR_NONE,
3402 ESYS_TR_NONE,
3403 ESYS_TR_NONE,
3404 &signature_hash,
3405 &policy_signature,
3406 &check_ticket_buffer);
3407 if (rc != TSS2_RC_SUCCESS)
3408 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3409 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
3410
3411 check_ticket = check_ticket_buffer;
3412 } else {
3413 /* When enrolling, we pass a NULL ticket */
3414 static const TPMT_TK_VERIFIED check_ticket_null = {
3415 .tag = TPM2_ST_VERIFIED,
3416 .hierarchy = TPM2_RH_OWNER,
3417 };
3418
3419 check_ticket = &check_ticket_null;
3420 }
3421
3422 rc = sym_Esys_PolicyAuthorize(
3423 c->esys_context,
3424 session->esys_handle,
3425 ESYS_TR_NONE,
3426 ESYS_TR_NONE,
3427 ESYS_TR_NONE,
3428 approved_policy,
3429 /* policyRef= */ &(const TPM2B_NONCE) {},
3430 pubkey_name,
3431 check_ticket);
3432 if (rc != TSS2_RC_SUCCESS)
3433 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3434 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
3435
3436 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3437}
3438
d9a1f1a7 3439/* Extend 'digest' with the calculated policy hash. */
9e437994 3440int tpm2_calculate_sealing_policy(
6e8fb3ad
DS
3441 const Tpm2PCRValue *pcr_values,
3442 size_t n_pcr_values,
d9a1f1a7 3443 const TPM2B_PUBLIC *public,
6e8fb3ad 3444 bool use_pin,
d9a1f1a7
DS
3445 TPM2B_DIGEST *digest) {
3446
3447 int r;
3448
6e8fb3ad 3449 assert(pcr_values || n_pcr_values == 0);
d9a1f1a7
DS
3450 assert(digest);
3451
3452 if (public) {
3453 r = tpm2_calculate_policy_authorize(public, NULL, digest);
3454 if (r < 0)
3455 return r;
3456 }
3457
6e8fb3ad
DS
3458 if (n_pcr_values > 0) {
3459 r = tpm2_calculate_policy_pcr(pcr_values, n_pcr_values, digest);
d9a1f1a7
DS
3460 if (r < 0)
3461 return r;
3462 }
3463
6e8fb3ad 3464 if (use_pin) {
d9a1f1a7
DS
3465 r = tpm2_calculate_policy_auth_value(digest);
3466 if (r < 0)
3467 return r;
3468 }
3469
3470 return 0;
3471}
3472
2cd9d575 3473static int tpm2_build_sealing_policy(
23e9ccc2 3474 Tpm2Context *c,
2cd9d575 3475 const Tpm2Handle *session,
d9b5841d 3476 uint32_t hash_pcr_mask,
2cd9d575 3477 uint16_t pcr_bank,
524cef3f
DS
3478 const TPM2B_PUBLIC *public,
3479 const void *fp,
3480 size_t fp_size,
d9b5841d
LP
3481 uint32_t pubkey_pcr_mask,
3482 JsonVariant *signature_json,
2f5a892a 3483 bool use_pin,
2cd9d575 3484 TPM2B_DIGEST **ret_policy_digest) {
5e521624 3485
5e521624
LP
3486 int r;
3487
3488 assert(c);
2cd9d575 3489 assert(session);
524cef3f 3490 assert(pubkey_pcr_mask == 0 || public);
5e521624 3491
2cd9d575 3492 log_debug("Building sealing policy.");
251d2ea2 3493
d9b5841d 3494 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
2cd9d575
DS
3495 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
3496 if (r < 0)
3497 return r;
3498 if (r == 0)
3499 log_warning("Selected TPM2 PCRs are not initialized on this system.");
d9b5841d 3500 }
321a9d9e 3501
d9b5841d 3502 if (pubkey_pcr_mask != 0) {
d9b5841d 3503 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 3504 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
524cef3f 3505 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
23b972d5
DS
3506 if (r < 0)
3507 return r;
d9b5841d
LP
3508 }
3509
3510 if (hash_pcr_mask != 0) {
d9b5841d 3511 TPML_PCR_SELECTION pcr_selection;
c69bd0ab 3512 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
dcbc4674
DS
3513 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
3514 if (r < 0)
3515 return r;
5e521624
LP
3516 }
3517
2f5a892a 3518 if (use_pin) {
8a716354
DS
3519 r = tpm2_policy_auth_value(c, session, NULL);
3520 if (r < 0)
3521 return r;
2f5a892a
GG
3522 }
3523
23b972d5
DS
3524 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
3525 if (r < 0)
3526 return r;
5e521624 3527
16e16b8c 3528 return 0;
5e521624
LP
3529}
3530
e3acb4d2 3531#if HAVE_OPENSSL
6761e135
DS
3532static const struct {
3533 TPM2_ECC_CURVE tpm2_ecc_curve_id;
3534 int openssl_ecc_curve_id;
3535} tpm2_openssl_ecc_curve_table[] = {
3536 { TPM2_ECC_NIST_P192, NID_X9_62_prime192v1, },
3537 { TPM2_ECC_NIST_P224, NID_secp224r1, },
3538 { TPM2_ECC_NIST_P256, NID_X9_62_prime256v1, },
3539 { TPM2_ECC_NIST_P384, NID_secp384r1, },
3540 { TPM2_ECC_NIST_P521, NID_secp521r1, },
3541 { TPM2_ECC_SM2_P256, NID_sm2, },
3542};
3543
3544static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id, TPM2_ECC_CURVE *ret) {
e3acb4d2
DS
3545 assert(ret);
3546
6761e135
DS
3547 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
3548 if (t->openssl_ecc_curve_id == openssl_ecc_curve_id) {
3549 *ret = t->tpm2_ecc_curve_id;
3550 return 0;
3551 }
e3acb4d2
DS
3552
3553 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
6761e135 3554 "Openssl ECC curve id %d not supported.", openssl_ecc_curve_id);
e3acb4d2
DS
3555}
3556
6761e135 3557static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id, int *ret) {
e3acb4d2
DS
3558 assert(ret);
3559
6761e135
DS
3560 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
3561 if (t->tpm2_ecc_curve_id == tpm2_ecc_curve_id) {
3562 *ret = t->openssl_ecc_curve_id;
3563 return 0;
3564 }
e3acb4d2
DS
3565
3566 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
6761e135 3567 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id);
e3acb4d2
DS
3568}
3569
3570#define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
3571
3572int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret) {
3573 int r;
3574
3575 assert(public);
3576 assert(ret);
3577
3578 const TPMT_PUBLIC *p = &public->publicArea;
3f4d5dfd
DS
3579 switch (p->type) {
3580 case TPM2_ALG_ECC: {
e3acb4d2
DS
3581 int curve_id;
3582 r = tpm2_ecc_curve_to_openssl_curve_id(p->parameters.eccDetail.curveID, &curve_id);
3583 if (r < 0)
3584 return r;
3585
3586 const TPMS_ECC_POINT *point = &p->unique.ecc;
3587 return ecc_pkey_from_curve_x_y(
3588 curve_id,
3589 point->x.buffer,
3590 point->x.size,
3591 point->y.buffer,
3592 point->y.size,
3593 ret);
3594 }
3f4d5dfd 3595 case TPM2_ALG_RSA: {
e3acb4d2
DS
3596 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
3597 * zero indicates that the exponent is the default of 2^16 + 1". */
3598 uint32_t exponent = htobe32(p->parameters.rsaDetail.exponent ?: TPM2_RSA_DEFAULT_EXPONENT);
3599 return rsa_pkey_from_n_e(
3600 p->unique.rsa.buffer,
3601 p->unique.rsa.size,
3602 &exponent,
3603 sizeof(exponent),
3604 ret);
3605 }
3f4d5dfd
DS
3606 default:
3607 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3608 "TPM2 asymmetric algorithm 0x%" PRIx16 " not supported.", p->type);
3609 }
e3acb4d2
DS
3610}
3611
3612int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) {
3613 int key_id, r;
3614
3615 assert(pkey);
3616 assert(ret);
3617
3618 TPMT_PUBLIC public = {
3619 .nameAlg = TPM2_ALG_SHA256,
3620 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
3621 .parameters.asymDetail = {
3622 .symmetric.algorithm = TPM2_ALG_NULL,
3623 .scheme.scheme = TPM2_ALG_NULL,
3624 },
3625 };
3626
3627#if OPENSSL_VERSION_MAJOR >= 3
3628 key_id = EVP_PKEY_get_id(pkey);
3629#else
3630 key_id = EVP_PKEY_id(pkey);
3631#endif
3632
3f4d5dfd
DS
3633 switch (key_id) {
3634 case EVP_PKEY_EC: {
e3acb4d2
DS
3635 public.type = TPM2_ALG_ECC;
3636
3637 int curve_id;
3638 _cleanup_free_ void *x = NULL, *y = NULL;
3639 size_t x_size, y_size;
3640 r = ecc_pkey_to_curve_x_y(pkey, &curve_id, &x, &x_size, &y, &y_size);
3641 if (r < 0)
ed35ac31 3642 return log_debug_errno(r, "Could not get ECC key curve/x/y: %m");
e3acb4d2
DS
3643
3644 TPM2_ECC_CURVE curve;
3645 r = tpm2_ecc_curve_from_openssl_curve_id(curve_id, &curve);
3646 if (r < 0)
3647 return r;
3648
3649 public.parameters.eccDetail.curveID = curve;
3650
3651 public.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
3652
3653 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
3654 if (r < 0)
ed35ac31 3655 return log_debug_errno(r, "ECC key x size %zu too large.", x_size);
e3acb4d2
DS
3656
3657 public.unique.ecc.x = TPM2B_ECC_PARAMETER_MAKE(x, x_size);
3658
3659 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
3660 if (r < 0)
ed35ac31 3661 return log_debug_errno(r, "ECC key y size %zu too large.", y_size);
e3acb4d2
DS
3662
3663 public.unique.ecc.y = TPM2B_ECC_PARAMETER_MAKE(y, y_size);
3f4d5dfd
DS
3664
3665 break;
3666 }
3667 case EVP_PKEY_RSA: {
e3acb4d2
DS
3668 public.type = TPM2_ALG_RSA;
3669
3670 _cleanup_free_ void *n = NULL, *e = NULL;
3671 size_t n_size, e_size;
3672 r = rsa_pkey_to_n_e(pkey, &n, &n_size, &e, &e_size);
3673 if (r < 0)
ed35ac31 3674 return log_debug_errno(r, "Could not get RSA key n/e: %m");
e3acb4d2
DS
3675
3676 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size);
3677 if (r < 0)
ed35ac31 3678 return log_debug_errno(r, "RSA key n size %zu too large.", n_size);
e3acb4d2
DS
3679
3680 public.unique.rsa = TPM2B_PUBLIC_KEY_RSA_MAKE(n, n_size);
3681 public.parameters.rsaDetail.keyBits = n_size * 8;
3682
3683 if (sizeof(uint32_t) < e_size)
ed35ac31 3684 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
e3acb4d2
DS
3685 "RSA key e size %zu too large.", e_size);
3686
3687 uint32_t exponent = 0;
70cb382d 3688 memcpy(&exponent, e, e_size);
e3acb4d2
DS
3689 exponent = be32toh(exponent) >> (32 - e_size * 8);
3690 if (exponent == TPM2_RSA_DEFAULT_EXPONENT)
3691 exponent = 0;
3692 public.parameters.rsaDetail.exponent = exponent;
3f4d5dfd
DS
3693
3694 break;
3695 }
3696 default:
e3acb4d2
DS
3697 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3698 "EVP_PKEY type %d not supported.", key_id);
3f4d5dfd 3699 }
e3acb4d2
DS
3700
3701 *ret = (TPM2B_PUBLIC) {
3702 .size = sizeof(public),
3703 .publicArea = public,
3704 };
3705
3706 return 0;
3707}
3708#endif
3709
3710int tpm2_tpm2b_public_to_fingerprint(
3711 const TPM2B_PUBLIC *public,
3712 void **ret_fingerprint,
3713 size_t *ret_fingerprint_size) {
3714
3715#if HAVE_OPENSSL
3716 int r;
3717
3718 assert(public);
3719 assert(ret_fingerprint);
3720 assert(ret_fingerprint_size);
3721
3722 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
3723 r = tpm2_tpm2b_public_to_openssl_pkey(public, &pkey);
3724 if (r < 0)
3725 return r;
3726
3727 /* Hardcode fingerprint to SHA256 */
3728 return pubkey_fingerprint(pkey, EVP_sha256(), ret_fingerprint, ret_fingerprint_size);
3729#else
3730 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3731#endif
3732}
3733
3734int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) {
3735#if HAVE_OPENSSL
3736 int r;
3737
3738 assert(pem);
3739 assert(ret);
3740
3741 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
3742 r = openssl_pkey_from_pem(pem, pem_size, &pkey);
3743 if (r < 0)
3744 return r;
3745
3746 return tpm2_tpm2b_public_from_openssl_pkey(pkey, ret);
3747#else
3748 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3749#endif
3750}
3751
9e437994
DS
3752int tpm2_seal(Tpm2Context *c,
3753 const TPM2B_DIGEST *policy,
d9b5841d
LP
3754 const char *pin,
3755 void **ret_secret,
3756 size_t *ret_secret_size,
3757 void **ret_blob,
3758 size_t *ret_blob_size,
acbb504e
WR
3759 uint16_t *ret_primary_alg,
3760 void **ret_srk_buf,
3761 size_t *ret_srk_buf_size) {
5e521624 3762
9e437994 3763 uint16_t primary_alg = 0;
5e521624
LP
3764 TSS2_RC rc;
3765 int r;
3766
3767 assert(ret_secret);
3768 assert(ret_secret_size);
3769 assert(ret_blob);
3770 assert(ret_blob_size);
5e521624
LP
3771
3772 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
3773 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
2b92a672
LP
3774 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
3775 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
3776 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
3777 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
3778 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
3779 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
3780 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
3781 * LUKS2 JSON header.
5e521624
LP
3782 *
3783 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
3784 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
3785 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
3786 * binding the unlocking to the TPM2 chip. */
3787
ee6a8713 3788 usec_t start = now(CLOCK_MONOTONIC);
692597c8 3789
5e521624
LP
3790 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
3791 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
3792 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
e3f1f210
DS
3793 TPMT_PUBLIC hmac_template = {
3794 .type = TPM2_ALG_KEYEDHASH,
3795 .nameAlg = TPM2_ALG_SHA256,
3796 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
3797 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
3798 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
9e437994 3799 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
5e521624
LP
3800 };
3801
e3f1f210
DS
3802 TPMS_SENSITIVE_CREATE hmac_sensitive = {
3803 .data.size = hmac_template.unique.keyedHash.size,
5e521624 3804 };
ee6a8713
DS
3805
3806 CLEANUP_ERASE(hmac_sensitive);
3807
94a4ff2d 3808 if (pin) {
f230572f 3809 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &hmac_sensitive.userAuth);
94a4ff2d
DS
3810 if (r < 0)
3811 return r;
3812 }
0e15c14f 3813
e3f1f210 3814 assert(sizeof(hmac_sensitive.data.buffer) >= hmac_sensitive.data.size);
5e521624 3815
23e9ccc2 3816 (void) tpm2_credit_random(c);
5e521624
LP
3817
3818 log_debug("Generating secret key data.");
3819
e3f1f210 3820 r = crypto_random_bytes(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
16e16b8c
DS
3821 if (r < 0)
3822 return log_error_errno(r, "Failed to generate secret key: %m");
5e521624 3823
1dc8f518 3824 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
cea525a9 3825 if (ret_srk_buf) {
9e437994
DS
3826 _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
3827 r = tpm2_get_or_create_srk(
3828 c,
3829 /* session= */ NULL,
3830 &primary_public,
3831 /* ret_name= */ NULL,
3832 /* ret_qname= */ NULL,
3833 &primary_handle);
cea525a9
DS
3834 if (r < 0)
3835 return r;
9e437994
DS
3836
3837 primary_alg = primary_public->publicArea.type;
cea525a9
DS
3838 } else {
3839 /* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
9e437994
DS
3840 primary_alg = TPM2_ALG_ECC;
3841
aff853f8 3842 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
9e437994 3843 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
cea525a9
DS
3844 if (r < 0)
3845 return log_error_errno(r, "Could not get legacy ECC template: %m");
3846
aff853f8 3847 if (!tpm2_supports_tpmt_public(c, &template.publicArea)) {
9e437994
DS
3848 primary_alg = TPM2_ALG_RSA;
3849
3850 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
cea525a9
DS
3851 if (r < 0)
3852 return log_error_errno(r, "Could not get legacy RSA template: %m");
3853
aff853f8 3854 if (!tpm2_supports_tpmt_public(c, &template.publicArea))
cea525a9
DS
3855 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3856 "TPM does not support either ECC or RSA legacy template.");
3857 }
3858
aff853f8 3859 r = tpm2_create_primary(
cea525a9 3860 c,
cea525a9
DS
3861 /* session= */ NULL,
3862 &template,
3863 /* sensitive= */ NULL,
9e437994 3864 /* ret_public= */ NULL,
cea525a9
DS
3865 &primary_handle);
3866 if (r < 0)
3867 return r;
3868 }
d9a1f1a7 3869
1dc8f518 3870 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
d9a1f1a7
DS
3871 r = tpm2_make_encryption_session(c, primary_handle, &TPM2_HANDLE_NONE, &encryption_session);
3872 if (r < 0)
3873 return r;
3874
ee6a8713
DS
3875 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
3876 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
e3f1f210
DS
3877 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
3878 if (r < 0)
3879 return r;
5e521624 3880
ee6a8713 3881 _cleanup_(erase_and_freep) void *secret = NULL;
e3f1f210 3882 secret = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
16e16b8c
DS
3883 if (!secret)
3884 return log_oom();
5e521624
LP
3885
3886 log_debug("Marshalling private and public part of HMAC key.");
3887
e8858f11
DS
3888 _cleanup_free_ void *blob = NULL;
3889 size_t max_size = sizeof(*private) + sizeof(*public), blob_size = 0;
5e521624 3890
e8858f11
DS
3891 blob = malloc0(max_size);
3892 if (!blob)
3893 return log_oom();
5e521624 3894
e8858f11
DS
3895 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
3896 if (rc != TSS2_RC_SUCCESS)
3897 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3898 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
5e521624 3899
e8858f11
DS
3900 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
3901 if (rc != TSS2_RC_SUCCESS)
3902 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3903 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
5e521624 3904
acbb504e
WR
3905 /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
3906 * the raw TPM handle as well as the object name. The object name is used to verify that
3907 * the key we use later is the key we expect to establish the session with.
3908 */
ee6a8713
DS
3909 _cleanup_(Esys_Freep) uint8_t *srk_buf = NULL;
3910 size_t srk_buf_size = 0;
acbb504e
WR
3911 if (ret_srk_buf) {
3912 log_debug("Serializing SRK ESYS_TR reference");
d9a1f1a7 3913 rc = sym_Esys_TR_Serialize(c->esys_context, primary_handle->esys_handle, &srk_buf, &srk_buf_size);
acbb504e
WR
3914 if (rc != TSS2_RC_SUCCESS)
3915 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3916 "Failed to serialize primary key: %s", sym_Tss2_RC_Decode(rc));
3917 }
3918
5291f26d
ZJS
3919 if (DEBUG_LOGGING)
3920 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624 3921
acbb504e
WR
3922 if (ret_srk_buf) {
3923 /*
3924 * make a copy since we don't want the caller to understand that
3925 * ESYS allocated the pointer. It would make tracking what deallocator
3926 * to use for srk_buf in which context a PITA.
3927 */
3928 void *tmp = memdup(srk_buf, srk_buf_size);
3929 if (!tmp)
3930 return log_oom();
3931
3932 *ret_srk_buf = TAKE_PTR(tmp);
3933 *ret_srk_buf_size = srk_buf_size;
3934 }
3935
5e521624 3936 *ret_secret = TAKE_PTR(secret);
e3f1f210 3937 *ret_secret_size = hmac_sensitive.data.size;
5e521624
LP
3938 *ret_blob = TAKE_PTR(blob);
3939 *ret_blob_size = blob_size;
9e437994
DS
3940
3941 if (ret_primary_alg)
3942 *ret_primary_alg = primary_alg;
5e521624 3943
16e16b8c 3944 return 0;
5e521624
LP
3945}
3946
0254e4d6
AAF
3947#define RETRY_UNSEAL_MAX 30u
3948
d9b5841d
LP
3949int tpm2_unseal(const char *device,
3950 uint32_t hash_pcr_mask,
07697bfe 3951 uint16_t pcr_bank,
d9b5841d
LP
3952 const void *pubkey,
3953 size_t pubkey_size,
3954 uint32_t pubkey_pcr_mask,
3955 JsonVariant *signature,
3956 const char *pin,
2b92a672 3957 uint16_t primary_alg,
5e521624
LP
3958 const void *blob,
3959 size_t blob_size,
3960 const void *known_policy_hash,
3961 size_t known_policy_hash_size,
acbb504e
WR
3962 const void *srk_buf,
3963 size_t srk_buf_size,
5e521624
LP
3964 void **ret_secret,
3965 size_t *ret_secret_size) {
3966
5e521624 3967 TSS2_RC rc;
5e521624
LP
3968 int r;
3969
3970 assert(blob);
3971 assert(blob_size > 0);
3972 assert(known_policy_hash_size == 0 || known_policy_hash);
d9b5841d 3973 assert(pubkey_size == 0 || pubkey);
5e521624
LP
3974 assert(ret_secret);
3975 assert(ret_secret_size);
3976
d9b5841d
LP
3977 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
3978 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5e521624 3979
1b30720c
LP
3980 r = dlopen_tpm2();
3981 if (r < 0)
3982 return log_error_errno(r, "TPM2 support is not installed.");
3983
5e521624 3984 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
dc176813
ZJS
3985 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
3986 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
3987 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
3988 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
3989 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5e521624
LP
3990 * and use it to unlock the LUKS2 volume. */
3991
98497426 3992 usec_t start = now(CLOCK_MONOTONIC);
5e521624
LP
3993
3994 log_debug("Unmarshalling private part of HMAC key.");
3995
98497426
DS
3996 TPM2B_PRIVATE private = {};
3997 size_t offset = 0;
5e521624
LP
3998 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
3999 if (rc != TSS2_RC_SUCCESS)
4000 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4001 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
4002
4003 log_debug("Unmarshalling public part of HMAC key.");
4004
98497426 4005 TPM2B_PUBLIC public = {};
5e521624
LP
4006 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
4007 if (rc != TSS2_RC_SUCCESS)
4008 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4009 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
4010
1dc8f518 4011 _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
68d084ce 4012 r = tpm2_context_new(device, &c);
5e521624
LP
4013 if (r < 0)
4014 return r;
4015
730d6ab9
DS
4016 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
4017 * so we need to handle that legacy situation. */
4018 if (pcr_bank == UINT16_MAX) {
4019 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
4020 if (r < 0)
4021 return r;
4022 }
4023
20988602 4024 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
acbb504e 4025 if (srk_buf) {
20988602 4026 r = tpm2_handle_new(c, &primary_handle);
acbb504e
WR
4027 if (r < 0)
4028 return r;
4029
20988602 4030 primary_handle->flush = false;
acbb504e
WR
4031
4032 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
4033 rc = sym_Esys_TR_Deserialize(
4034 c->esys_context,
4035 srk_buf,
4036 srk_buf_size,
20988602 4037 &primary_handle->esys_handle);
acbb504e
WR
4038 if (rc != TSS2_RC_SUCCESS)
4039 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4040 "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc));
20988602 4041 } else if (primary_alg != 0) {
aff853f8
DS
4042 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
4043 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
20988602
DS
4044 if (r < 0)
4045 return log_error_errno(r, "Could not get legacy template: %m");
4046
aff853f8 4047 r = tpm2_create_primary(
20988602 4048 c,
20988602
DS
4049 /* session= */ NULL,
4050 &template,
4051 /* sensitive= */ NULL,
4052 /* ret_public= */ NULL,
20988602 4053 &primary_handle);
acbb504e
WR
4054 if (r < 0)
4055 return r;
20988602
DS
4056 } else
4057 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4058 "No SRK or primary alg provided.");
da29de23 4059
5e521624
LP
4060 log_debug("Loading HMAC key into TPM.");
4061
0e15c14f
WR
4062 /*
4063 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
acbb504e
WR
4064 * gives you back a different key, the session initiation will fail. In the
4065 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
4066 * provides protections.
0e15c14f 4067 */
1dc8f518 4068 _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
20988602 4069 r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
16e16b8c
DS
4070 if (r < 0)
4071 return r;
4072
e3acb4d2 4073 TPM2B_PUBLIC pubkey_tpm2b;
524cef3f
DS
4074 _cleanup_free_ void *fp = NULL;
4075 size_t fp_size = 0;
4076 if (pubkey) {
e3acb4d2 4077 r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &pubkey_tpm2b);
524cef3f 4078 if (r < 0)
e3acb4d2
DS
4079 return log_error_errno(r, "Could not create TPMT_PUBLIC: %m");
4080
4081 r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp, &fp_size);
4082 if (r < 0)
4083 return log_error_errno(r, "Could not get key fingerprint: %m");
524cef3f
DS
4084 }
4085
409a65f8
DS
4086 /*
4087 * if a pin is set for the seal object, use it to bind the session
4088 * key to that object. This prevents active bus interposers from
4089 * faking a TPM and seeing the unsealed value. An active interposer
4090 * could fake a TPM, satisfying the encrypted session, and just
4091 * forward everything to the *real* TPM.
4092 */
4093 r = tpm2_set_auth(c, hmac_key, pin);
4094 if (r < 0)
4095 return r;
4096
1dc8f518 4097 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
20988602 4098 r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
0e15c14f 4099 if (r < 0)
16e16b8c 4100 return r;
2f5a892a 4101
98497426 4102 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
0254e4d6 4103 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
1dc8f518 4104 _cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
23b972d5 4105 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
0254e4d6 4106 r = tpm2_make_policy_session(
23e9ccc2 4107 c,
20988602 4108 primary_handle,
2cd9d575
DS
4109 encryption_session,
4110 /* trial= */ false,
4111 &policy_session);
4112 if (r < 0)
4113 return r;
4114
4115 r = tpm2_build_sealing_policy(
4116 c,
4117 policy_session,
0254e4d6
AAF
4118 hash_pcr_mask,
4119 pcr_bank,
e3acb4d2 4120 pubkey ? &pubkey_tpm2b : NULL,
524cef3f 4121 fp, fp_size,
0254e4d6
AAF
4122 pubkey_pcr_mask,
4123 signature,
4124 !!pin,
2cd9d575 4125 &policy_digest);
0254e4d6 4126 if (r < 0)
16e16b8c 4127 return r;
2f5a892a 4128
0254e4d6
AAF
4129 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
4130 * wait until the TPM2 tells us to go away. */
4131 if (known_policy_hash_size > 0 &&
4132 memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
4133 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
4134 "Current policy digest does not match stored policy digest, cancelling "
4135 "TPM2 authentication attempt.");
2f5a892a 4136
0254e4d6 4137 log_debug("Unsealing HMAC key.");
5e521624 4138
0254e4d6 4139 rc = sym_Esys_Unseal(
68d084ce 4140 c->esys_context,
16e16b8c
DS
4141 hmac_key->esys_handle,
4142 policy_session->esys_handle,
2cd9d575 4143 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
0254e4d6
AAF
4144 ESYS_TR_NONE,
4145 &unsealed);
16e16b8c
DS
4146 if (rc == TSS2_RC_SUCCESS)
4147 break;
4148 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
4149 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4150 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
4151 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5e521624
LP
4152 }
4153
98497426 4154 _cleanup_(erase_and_freep) char *secret = NULL;
5e521624
LP
4155 secret = memdup(unsealed->buffer, unsealed->size);
4156 explicit_bzero_safe(unsealed->buffer, unsealed->size);
16e16b8c
DS
4157 if (!secret)
4158 return log_oom();
5e521624 4159
5291f26d
ZJS
4160 if (DEBUG_LOGGING)
4161 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5e521624
LP
4162
4163 *ret_secret = TAKE_PTR(secret);
4164 *ret_secret_size = unsealed->size;
4165
16e16b8c 4166 return 0;
5e521624
LP
4167}
4168
4169#endif
4170
4171int tpm2_list_devices(void) {
4172#if HAVE_TPM2
4173 _cleanup_(table_unrefp) Table *t = NULL;
5d2a48da 4174 _cleanup_closedir_ DIR *d = NULL;
5e521624
LP
4175 int r;
4176
4177 r = dlopen_tpm2();
4178 if (r < 0)
4179 return log_error_errno(r, "TPM2 support is not installed.");
4180
4181 t = table_new("path", "device", "driver");
4182 if (!t)
4183 return log_oom();
4184
4185 d = opendir("/sys/class/tpmrm");
4186 if (!d) {
4187 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
4188 if (errno != ENOENT)
4189 return -errno;
4190 } else {
4191 for (;;) {
4192 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
4193 struct dirent *de;
4194
4195 de = readdir_no_dot(d);
4196 if (!de)
4197 break;
4198
4199 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
4200 if (!device_path)
4201 return log_oom();
4202
4203 r = readlink_malloc(device_path, &device);
4204 if (r < 0)
4205 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
4206 else {
4207 driver_path = path_join(device_path, "driver");
4208 if (!driver_path)
4209 return log_oom();
4210
4211 r = readlink_malloc(driver_path, &driver);
4212 if (r < 0)
4213 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
4214 }
4215
4216 node = path_join("/dev", de->d_name);
4217 if (!node)
4218 return log_oom();
4219
4220 r = table_add_many(
4221 t,
4222 TABLE_PATH, node,
4223 TABLE_STRING, device ? last_path_component(device) : NULL,
4224 TABLE_STRING, driver ? last_path_component(driver) : NULL);
4225 if (r < 0)
4226 return table_log_add_error(r);
4227 }
4228 }
4229
4230 if (table_get_rows(t) <= 1) {
4231 log_info("No suitable TPM2 devices found.");
4232 return 0;
4233 }
4234
4235 r = table_print(t, stdout);
4236 if (r < 0)
4237 return log_error_errno(r, "Failed to show device table: %m");
4238
4239 return 0;
4240#else
4241 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4242 "TPM2 not supported on this build.");
4243#endif
4244}
4245
4246int tpm2_find_device_auto(
4247 int log_level, /* log level when no device is found */
4248 char **ret) {
4249#if HAVE_TPM2
5d2a48da 4250 _cleanup_closedir_ DIR *d = NULL;
5e521624
LP
4251 int r;
4252
4253 r = dlopen_tpm2();
4254 if (r < 0)
4255 return log_error_errno(r, "TPM2 support is not installed.");
4256
4257 d = opendir("/sys/class/tpmrm");
4258 if (!d) {
4259 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
4260 "Failed to open /sys/class/tpmrm: %m");
4261 if (errno != ENOENT)
4262 return -errno;
4263 } else {
4264 _cleanup_free_ char *node = NULL;
4265
4266 for (;;) {
4267 struct dirent *de;
4268
4269 de = readdir_no_dot(d);
4270 if (!de)
4271 break;
4272
4273 if (node)
4274 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
4275 "More than one TPM2 (tpmrm) device found.");
4276
4277 node = path_join("/dev", de->d_name);
4278 if (!node)
4279 return log_oom();
4280 }
4281
4282 if (node) {
4283 *ret = TAKE_PTR(node);
4284 return 0;
4285 }
4286 }
4287
4288 return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
4289#else
4290 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4291 "TPM2 not supported on this build.");
4292#endif
4293}
4294
15c591d1
LP
4295#if HAVE_TPM2
4296int tpm2_extend_bytes(
23e9ccc2 4297 Tpm2Context *c,
15c591d1
LP
4298 char **banks,
4299 unsigned pcr_index,
4300 const void *data,
9885c874
LP
4301 size_t data_size,
4302 const void *secret,
4303 size_t secret_size) {
15c591d1
LP
4304
4305#if HAVE_OPENSSL
4306 TPML_DIGEST_VALUES values = {};
4307 TSS2_RC rc;
4308
4309 assert(c);
9885c874
LP
4310 assert(data || data_size == 0);
4311 assert(secret || secret_size == 0);
4312
4313 if (data_size == SIZE_MAX)
4314 data_size = strlen(data);
4315 if (secret_size == SIZE_MAX)
4316 secret_size = strlen(secret);
15c591d1
LP
4317
4318 if (pcr_index >= TPM2_PCRS_MAX)
4319 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
4320
4321 if (strv_isempty(banks))
4322 return 0;
4323
4324 STRV_FOREACH(bank, banks) {
4325 const EVP_MD *implementation;
4326 int id;
4327
4328 assert_se(implementation = EVP_get_digestbyname(*bank));
4329
4330 if (values.count >= ELEMENTSOF(values.digests))
4331 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
4332
4333 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
4334 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
4335
7bfe0a48 4336 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
15c591d1
LP
4337 if (id < 0)
4338 return log_error_errno(id, "Can't map hash name to TPM2.");
4339
4340 values.digests[values.count].hashAlg = id;
4341
9885c874
LP
4342 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
4343 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
4344 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
4345 * secret for other purposes, maybe because it needs a shorter secret derived from it for
4346 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
4347 * private non-secret string instead. */
4348 if (secret_size > 0) {
4349 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
4350 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
4351 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
4352 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
15c591d1
LP
4353
4354 values.count++;
4355 }
4356
4357 rc = sym_Esys_PCR_Extend(
23e9ccc2 4358 c->esys_context,
15c591d1
LP
4359 ESYS_TR_PCR0 + pcr_index,
4360 ESYS_TR_PASSWORD,
4361 ESYS_TR_NONE,
4362 ESYS_TR_NONE,
4363 &values);
4364 if (rc != TSS2_RC_SUCCESS)
4365 return log_error_errno(
4366 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4367 "Failed to measure into PCR %u: %s",
4368 pcr_index,
4369 sym_Tss2_RC_Decode(rc));
4370
4371 return 0;
0d7009d3
DS
4372#else /* HAVE_OPENSSL */
4373 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
15c591d1
LP
4374#endif
4375}
4376#endif
4377
c69bd0ab
DS
4378char *tpm2_pcr_mask_to_string(uint32_t mask) {
4379 _cleanup_free_ char *s = NULL;
4380
4381 FOREACH_PCR_IN_MASK(n, mask)
4382 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
4383 return NULL;
4384
4385 if (!s)
4386 return strdup("");
4387
4388 return TAKE_PTR(s);
4389}
4390
4436081e
LP
4391int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
4392 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
4436081e
LP
4393 int r;
4394
c22dcd67
YW
4395 assert(ret);
4396
4397 for (size_t i = 0; i < TPM2_PCRS_MAX; i++) {
4398 _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
4399
4436081e
LP
4400 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
4401 continue;
4402
c22dcd67 4403 r = json_variant_new_integer(&e, i);
4436081e 4404 if (r < 0)
c22dcd67 4405 return r;
4436081e 4406
c22dcd67
YW
4407 r = json_variant_append_array(&a, e);
4408 if (r < 0)
4409 return r;
4436081e
LP
4410 }
4411
c22dcd67
YW
4412 if (!a)
4413 return json_variant_new_array(ret, NULL, 0);
4436081e 4414
c22dcd67
YW
4415 *ret = TAKE_PTR(a);
4416 return 0;
4436081e 4417}
8de8ec88
LP
4418
4419int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
4420 JsonVariant *e;
4421 uint32_t mask = 0;
4422
4423 if (!json_variant_is_array(v))
4424 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
4425
4426 JSON_VARIANT_ARRAY_FOREACH(e, v) {
4427 uint64_t u;
4428
4429 if (!json_variant_is_unsigned(e))
4430 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
4431
4432 u = json_variant_unsigned(e);
4433 if (u >= TPM2_PCRS_MAX)
4434 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
4435
4436 mask |= UINT32_C(1) << u;
4437 }
4438
4439 if (ret)
4440 *ret = mask;
4441
4442 return 0;
4443}
4436081e 4444
5e521624
LP
4445int tpm2_make_luks2_json(
4446 int keyslot,
f0f4fcae 4447 uint32_t hash_pcr_mask,
07697bfe 4448 uint16_t pcr_bank,
f0f4fcae
LP
4449 const void *pubkey,
4450 size_t pubkey_size,
4451 uint32_t pubkey_pcr_mask,
2b92a672 4452 uint16_t primary_alg,
5e521624
LP
4453 const void *blob,
4454 size_t blob_size,
4455 const void *policy_hash,
4456 size_t policy_hash_size,
aae6eb96
WR
4457 const void *salt,
4458 size_t salt_size,
acbb504e
WR
4459 const void *srk_buf,
4460 size_t srk_buf_size,
6c7a1681 4461 TPM2Flags flags,
5e521624
LP
4462 JsonVariant **ret) {
4463
f0f4fcae 4464 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
5e521624 4465 _cleanup_free_ char *keyslot_as_string = NULL;
5e521624
LP
4466 int r;
4467
4468 assert(blob || blob_size == 0);
4469 assert(policy_hash || policy_hash_size == 0);
f0f4fcae 4470 assert(pubkey || pubkey_size == 0);
5e521624
LP
4471
4472 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
4473 return -ENOMEM;
4474
f0f4fcae 4475 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
5e521624 4476 if (r < 0)
4436081e 4477 return r;
5e521624 4478
f0f4fcae
LP
4479 if (pubkey_pcr_mask != 0) {
4480 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
4481 if (r < 0)
4482 return r;
4483 }
4484
4485 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
4486 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
4487 * object should use "_" rather than "-" in field names. */
4488
5e521624
LP
4489 r = json_build(&v,
4490 JSON_BUILD_OBJECT(
0cdf6b14 4491 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
5e521624
LP
4492 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
4493 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
f0f4fcae 4494 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7bfe0a48
DS
4495 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
4496 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 4497 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
f0f4fcae
LP
4498 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
4499 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
aae6eb96 4500 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
acbb504e
WR
4501 JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size)),
4502 JSON_BUILD_PAIR_CONDITION(srk_buf, "tpm2_srk", JSON_BUILD_BASE64(srk_buf, srk_buf_size))));
5e521624
LP
4503 if (r < 0)
4504 return r;
4505
4506 if (ret)
4507 *ret = TAKE_PTR(v);
4508
4509 return keyslot;
4510}
07697bfe 4511
fdf6c27c
LP
4512int tpm2_parse_luks2_json(
4513 JsonVariant *v,
4514 int *ret_keyslot,
4515 uint32_t *ret_hash_pcr_mask,
4516 uint16_t *ret_pcr_bank,
4517 void **ret_pubkey,
4518 size_t *ret_pubkey_size,
4519 uint32_t *ret_pubkey_pcr_mask,
4520 uint16_t *ret_primary_alg,
4521 void **ret_blob,
4522 size_t *ret_blob_size,
4523 void **ret_policy_hash,
4524 size_t *ret_policy_hash_size,
aae6eb96
WR
4525 void **ret_salt,
4526 size_t *ret_salt_size,
acbb504e
WR
4527 void **ret_srk_buf,
4528 size_t *ret_srk_buf_size,
fdf6c27c
LP
4529 TPM2Flags *ret_flags) {
4530
acbb504e
WR
4531 _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
4532 size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
fdf6c27c
LP
4533 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
4534 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
4535 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
4536 int r, keyslot = -1;
4537 TPM2Flags flags = 0;
4538 JsonVariant *w;
4539
4540 assert(v);
4541
4542 if (ret_keyslot) {
4543 keyslot = cryptsetup_get_keyslot_from_token(v);
4544 if (keyslot < 0) {
4545 /* Return a recognizable error when parsing this field, so that callers can handle parsing
4546 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
4547 * spec */
4548 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
4549 return -EUCLEAN;
4550 }
4551 }
4552
4553 w = json_variant_by_key(v, "tpm2-pcrs");
4554 if (!w)
4555 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
4556
4557 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
4558 if (r < 0)
4559 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
4560
4561 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
4562 * to SHA256. */
4563 w = json_variant_by_key(v, "tpm2-pcr-bank");
4564 if (w) {
4565 /* The PCR bank field is optional */
4566
4567 if (!json_variant_is_string(w))
4568 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
4569
7bfe0a48 4570 r = tpm2_hash_alg_from_string(json_variant_string(w));
fdf6c27c
LP
4571 if (r < 0)
4572 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
4573
4574 pcr_bank = r;
4575 }
4576
4577 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
4578 * the algorithm was hardcoded to ECC. */
4579 w = json_variant_by_key(v, "tpm2-primary-alg");
4580 if (w) {
4581 /* The primary key algorithm is optional */
4582
4583 if (!json_variant_is_string(w))
4584 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
4585
7bfe0a48 4586 r = tpm2_asym_alg_from_string(json_variant_string(w));
fdf6c27c 4587 if (r < 0)
7bfe0a48 4588 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
fdf6c27c
LP
4589
4590 primary_alg = r;
4591 }
4592
4593 w = json_variant_by_key(v, "tpm2-blob");
4594 if (!w)
4595 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
4596
4597 r = json_variant_unbase64(w, &blob, &blob_size);
4598 if (r < 0)
4599 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
4600
4601 w = json_variant_by_key(v, "tpm2-policy-hash");
4602 if (!w)
4603 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
4604
4605 r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
4606 if (r < 0)
4607 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
4608
4609 w = json_variant_by_key(v, "tpm2-pin");
4610 if (w) {
4611 if (!json_variant_is_boolean(w))
4612 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
4613
4614 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
4615 }
4616
aae6eb96
WR
4617 w = json_variant_by_key(v, "tpm2_salt");
4618 if (w) {
4619 r = json_variant_unbase64(w, &salt, &salt_size);
4620 if (r < 0)
4621 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
4622 }
4623
fdf6c27c
LP
4624 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
4625 if (w) {
4626 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
4627 if (r < 0)
4628 return r;
4629 }
4630
4631 w = json_variant_by_key(v, "tpm2_pubkey");
4632 if (w) {
4633 r = json_variant_unbase64(w, &pubkey, &pubkey_size);
4634 if (r < 0)
4635 return log_debug_errno(r, "Failed to decode PCR public key.");
4636 } else if (pubkey_pcr_mask != 0)
4637 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
4638
acbb504e
WR
4639 w = json_variant_by_key(v, "tpm2_srk");
4640 if (w) {
4641 r = json_variant_unbase64(w, &srk_buf, &srk_buf_size);
4642 if (r < 0)
4643 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
4644 }
4645
fdf6c27c
LP
4646 if (ret_keyslot)
4647 *ret_keyslot = keyslot;
4648 if (ret_hash_pcr_mask)
4649 *ret_hash_pcr_mask = hash_pcr_mask;
4650 if (ret_pcr_bank)
4651 *ret_pcr_bank = pcr_bank;
4652 if (ret_pubkey)
4653 *ret_pubkey = TAKE_PTR(pubkey);
4654 if (ret_pubkey_size)
4655 *ret_pubkey_size = pubkey_size;
4656 if (ret_pubkey_pcr_mask)
4657 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
4658 if (ret_primary_alg)
4659 *ret_primary_alg = primary_alg;
4660 if (ret_blob)
4661 *ret_blob = TAKE_PTR(blob);
4662 if (ret_blob_size)
4663 *ret_blob_size = blob_size;
4664 if (ret_policy_hash)
4665 *ret_policy_hash = TAKE_PTR(policy_hash);
4666 if (ret_policy_hash_size)
4667 *ret_policy_hash_size = policy_hash_size;
aae6eb96
WR
4668 if (ret_salt)
4669 *ret_salt = TAKE_PTR(salt);
4670 if (ret_salt_size)
4671 *ret_salt_size = salt_size;
fdf6c27c
LP
4672 if (ret_flags)
4673 *ret_flags = flags;
acbb504e
WR
4674 if (ret_srk_buf)
4675 *ret_srk_buf = TAKE_PTR(srk_buf);
4676 if (ret_srk_buf_size)
4677 *ret_srk_buf_size = srk_buf_size;
fdf6c27c
LP
4678
4679 return 0;
4680}
4681
c9df1fb1 4682int tpm2_hash_alg_to_size(uint16_t alg) {
7354a7cc
DS
4683 switch (alg) {
4684 case TPM2_ALG_SHA1:
c9df1fb1 4685 return 20;
7354a7cc 4686 case TPM2_ALG_SHA256:
c9df1fb1 4687 return 32;
7354a7cc 4688 case TPM2_ALG_SHA384:
c9df1fb1 4689 return 48;
7354a7cc 4690 case TPM2_ALG_SHA512:
c9df1fb1 4691 return 64;
7354a7cc
DS
4692 default:
4693 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm id 0x%" PRIx16, alg);
4694 }
c9df1fb1
DS
4695}
4696
7bfe0a48 4697const char *tpm2_hash_alg_to_string(uint16_t alg) {
7354a7cc
DS
4698 switch (alg) {
4699 case TPM2_ALG_SHA1:
07697bfe 4700 return "sha1";
7354a7cc 4701 case TPM2_ALG_SHA256:
98193c39 4702 return "sha256";
7354a7cc 4703 case TPM2_ALG_SHA384:
98193c39 4704 return "sha384";
7354a7cc 4705 case TPM2_ALG_SHA512:
98193c39 4706 return "sha512";
7354a7cc
DS
4707 default:
4708 log_debug("Unknown hash algorithm id 0x%" PRIx16, alg);
4709 return NULL;
4710 }
07697bfe
LP
4711}
4712
7bfe0a48
DS
4713int tpm2_hash_alg_from_string(const char *alg) {
4714 if (strcaseeq_ptr(alg, "sha1"))
07697bfe 4715 return TPM2_ALG_SHA1;
7bfe0a48 4716 if (strcaseeq_ptr(alg, "sha256"))
98193c39 4717 return TPM2_ALG_SHA256;
7bfe0a48 4718 if (strcaseeq_ptr(alg, "sha384"))
98193c39 4719 return TPM2_ALG_SHA384;
7bfe0a48 4720 if (strcaseeq_ptr(alg, "sha512"))
98193c39 4721 return TPM2_ALG_SHA512;
240774f5 4722 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm name '%s'", alg);
07697bfe 4723}
2b92a672 4724
7bfe0a48 4725const char *tpm2_asym_alg_to_string(uint16_t alg) {
7354a7cc
DS
4726 switch (alg) {
4727 case TPM2_ALG_ECC:
2b92a672 4728 return "ecc";
7354a7cc 4729 case TPM2_ALG_RSA:
2b92a672 4730 return "rsa";
7354a7cc
DS
4731 default:
4732 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16, alg);
4733 return NULL;
4734 }
2b92a672
LP
4735}
4736
7bfe0a48 4737int tpm2_asym_alg_from_string(const char *alg) {
f92ebc86 4738 if (strcaseeq_ptr(alg, "ecc"))
2b92a672 4739 return TPM2_ALG_ECC;
f92ebc86 4740 if (strcaseeq_ptr(alg, "rsa"))
2b92a672 4741 return TPM2_ALG_RSA;
240774f5 4742 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown asymmetric algorithm name '%s'", alg);
2b92a672 4743}
ba578556
LP
4744
4745Tpm2Support tpm2_support(void) {
4746 Tpm2Support support = TPM2_SUPPORT_NONE;
4747 int r;
4748
44d5dd65
LP
4749 if (detect_container() <= 0) {
4750 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
4751 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
4752 * let's assume containers never have a TPM, at least for now. */
4753
db55bbf2 4754 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
44d5dd65
LP
4755 if (r < 0) {
4756 if (r != -ENOENT)
4757 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
4758 } else if (r == 0) /* populated! */
300bba79
DDM
4759 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
4760 else
4761 /* If the directory exists but is empty, we know the subsystem is enabled but no
4762 * driver has been loaded yet. */
4763 support |= TPM2_SUPPORT_SUBSYSTEM;
44d5dd65 4764 }
ba578556
LP
4765
4766 if (efi_has_tpm2())
4767 support |= TPM2_SUPPORT_FIRMWARE;
4768
4769#if HAVE_TPM2
4770 support |= TPM2_SUPPORT_SYSTEM;
33931049
DDM
4771
4772 r = dlopen_tpm2();
4773 if (r >= 0)
4774 support |= TPM2_SUPPORT_LIBRARIES;
ba578556
LP
4775#endif
4776
4777 return support;
4778}
222a951f 4779
07c04061
DS
4780#if HAVE_TPM2
4781static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
4782 TPMI_ALG_HASH default_hash = 0;
193fd573
DS
4783 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
4784 if (v->hash != 0) {
4785 default_hash = v->hash;
07c04061
DS
4786 break;
4787 }
4788
4789 if (default_hash != 0)
193fd573
DS
4790 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
4791 if (v->hash == 0)
4792 v->hash = default_hash;
07c04061
DS
4793}
4794#endif
4795
4796/* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
4797 *
4798 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
4799 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
4800 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
4801 *
4802 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
4803 * tpm2_parse_pcr_argument_append(). */
4804int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
4805#if HAVE_TPM2
222a951f
LP
4806 int r;
4807
07c04061
DS
4808 assert(arg);
4809 assert(ret_pcr_values);
4810 assert(ret_n_pcr_values);
222a951f 4811
07c04061
DS
4812 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
4813 size_t n_pcr_values = 0;
4814 r = tpm2_pcr_values_from_string(arg, &pcr_values, &n_pcr_values);
4815 if (r < 0)
4816 return r;
4817
4818 tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
4819
4820 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
4821
cc1a78d5 4822 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
07c04061
DS
4823 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
4824
4825 *ret_pcr_values = TAKE_PTR(pcr_values);
4826 *ret_n_pcr_values = n_pcr_values;
222a951f 4827
07c04061
DS
4828 return 0;
4829#else
4830 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
4831#endif
4832}
4833
4834/* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
4835 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
4836 * must be correct.
4837 *
4838 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
4839 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
4840 * algorithm check applied again (in case either the previous or current array had no default hash
4841 * algorithm), and then the resulting array is sorted and rechecked for validity. */
ae2b38e4 4842int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values) {
07c04061
DS
4843#if HAVE_TPM2
4844 int r;
4845
4846 assert(arg);
ae2b38e4
DS
4847 assert(pcr_values);
4848 assert(n_pcr_values);
07c04061 4849
ae2b38e4
DS
4850 _cleanup_free_ Tpm2PCRValue *more_pcr_values = NULL;
4851 size_t n_more_pcr_values;
4852 r = tpm2_parse_pcr_argument(arg, &more_pcr_values, &n_more_pcr_values);
07c04061
DS
4853 if (r < 0)
4854 return r;
4855
4856 /* If we got previous values, append them. */
ae2b38e4 4857 if (*pcr_values && !GREEDY_REALLOC_APPEND(more_pcr_values, n_more_pcr_values, *pcr_values, *n_pcr_values))
07c04061
DS
4858 return log_oom();
4859
ae2b38e4 4860 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values, n_more_pcr_values);
07c04061 4861
ae2b38e4 4862 tpm2_sort_pcr_values(more_pcr_values, n_more_pcr_values);
07c04061 4863
ae2b38e4 4864 if (!tpm2_pcr_values_valid(more_pcr_values, n_more_pcr_values))
07c04061
DS
4865 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
4866
ae2b38e4
DS
4867 SWAP_TWO(*pcr_values, more_pcr_values);
4868 *n_pcr_values = n_more_pcr_values;
07c04061
DS
4869
4870 return 0;
4871#else
4872 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
4873#endif
4874}
4875
4876/* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
4877 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
4878 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
4879 * UINT32_MAX, and or-ing the mask otherwise. */
4880int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *ret_mask) {
4881#if HAVE_TPM2
4882 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
4883 size_t n_pcr_values;
4884 int r;
4885
4886 assert(arg);
4887 assert(ret_mask);
4888
4889 r = tpm2_parse_pcr_argument(arg, &pcr_values, &n_pcr_values);
4890 if (r < 0)
4891 return r;
4892
4893 if (n_pcr_values == 0) {
4894 /* This retains the previous behavior of clearing the mask if the arg is empty */
4895 *ret_mask = 0;
222a951f
LP
4896 return 0;
4897 }
4898
07c04061
DS
4899 size_t hash_count;
4900 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
222a951f 4901 if (r < 0)
07c04061
DS
4902 return log_error_errno(r, "Could not get hash count from pcr values: %m");
4903
4904 if (hash_count > 1)
4905 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR hash banks selected.");
4906
4907 uint32_t new_mask;
4908 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
4909 if (r < 0)
4910 return log_error_errno(r, "Could not get pcr values mask: %m");
222a951f 4911
07c04061
DS
4912 if (*ret_mask == UINT32_MAX)
4913 *ret_mask = new_mask;
222a951f 4914 else
07c04061 4915 *ret_mask |= new_mask;
222a951f
LP
4916
4917 return 0;
07c04061
DS
4918#else
4919 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
4920#endif
222a951f 4921}
6a0779cb
LP
4922
4923int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
6270b2e6 4924 _cleanup_strv_free_ char **search = NULL;
6a0779cb
LP
4925 _cleanup_free_ char *discovered_path = NULL;
4926 _cleanup_fclose_ FILE *f = NULL;
4927 int r;
4928
4929 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
4930 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4931
6270b2e6
LP
4932 search = strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
4933 if (!search)
4934 return log_oom();
4935
4936 if (!path) {
4937 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
4938 * this case include /.extra/ in the search path, but only in this case, and if we run in the
4939 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
4940
6a0779cb
LP
4941 path = "tpm2-pcr-signature.json";
4942
6270b2e6
LP
4943 if (in_initrd())
4944 if (strv_extend(&search, "/.extra") < 0)
4945 return log_oom();
4946 }
4947
4948 r = search_and_fopen(path, "re", NULL, (const char**) search, &f, &discovered_path);
6a0779cb
LP
4949 if (r < 0)
4950 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
4951
4952 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
4953 if (r < 0)
4954 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
4955
4956 return 0;
4957}
4958
4959int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
4960 _cleanup_free_ char *discovered_path = NULL;
4961 _cleanup_fclose_ FILE *f = NULL;
4962 int r;
4963
4964 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
4965 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
4966
4967 if (!path)
4968 path = "tpm2-pcr-public-key.pem";
4969
4970 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
4971 if (r < 0)
4972 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
4973
4974 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
4975 if (r < 0)
4976 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
4977
4978 return 0;
4979}
4d5cc0d4 4980
aae6eb96
WR
4981#define PBKDF2_HMAC_SHA256_ITERATIONS 10000
4982
4983/*
4984 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
4985 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
4986 * I found the wikipedia entry relevant and it contains links to
4987 * relevant RFCs:
4988 * - https://en.wikipedia.org/wiki/PBKDF2
4989 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
4990 */
4991int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
4992 size_t passlen,
4993 const void *salt,
4994 size_t saltlen,
4995 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
4996
4997 uint8_t _cleanup_(erase_and_freep) *buffer = NULL;
4998 uint8_t u[SHA256_DIGEST_SIZE];
4999
5000 /* To keep this simple, since derived KeyLen (dkLen in docs)
5001 * Is the same as the hash output, we don't need multiple
5002 * blocks. Part of the algorithm is to add the block count
5003 * in, but this can be hardcoded to 1.
5004 */
5005 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
5006
504d0acf 5007 assert (salt);
aae6eb96
WR
5008 assert (saltlen > 0);
5009 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
5010 assert (passlen > 0);
5011
5012 /*
5013 * Build a buffer of salt + block_cnt and hmac_sha256 it we
5014 * do this as we don't have a context builder for HMAC_SHA256.
5015 */
5016 buffer = malloc(saltlen + sizeof(block_cnt));
5017 if (!buffer)
5018 return -ENOMEM;
5019
5020 memcpy(buffer, salt, saltlen);
5021 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
5022
5023 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
5024
5025 /* dk needs to be an unmodified u as u gets modified in the loop */
5026 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
5027 uint8_t *dk = ret_key;
5028
5029 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
5030 hmac_sha256(pass, passlen, u, sizeof(u), u);
5031
5032 for (size_t j=0; j < sizeof(u); j++)
5033 dk[j] ^= u[j];
5034 }
5035
5036 return 0;
5037}
96ead603 5038
2099cd62
LP
5039static const char* const tpm2_pcr_index_table[_TPM2_PCR_INDEX_MAX_DEFINED] = {
5040 [TPM2_PCR_PLATFORM_CODE] = "platform-code",
5041 [TPM2_PCR_PLATFORM_CONFIG] = "platform-config",
5042 [TPM2_PCR_EXTERNAL_CODE] = "external-code",
5043 [TPM2_PCR_EXTERNAL_CONFIG] = "external-config",
5044 [TPM2_PCR_BOOT_LOADER_CODE] = "boot-loader-code",
5045 [TPM2_PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
5046 [TPM2_PCR_HOST_PLATFORM] = "host-platform",
5047 [TPM2_PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
5048 [TPM2_PCR_KERNEL_INITRD] = "kernel-initrd",
5049 [TPM2_PCR_IMA] = "ima",
5050 [TPM2_PCR_KERNEL_BOOT] = "kernel-boot",
5051 [TPM2_PCR_KERNEL_CONFIG] = "kernel-config",
5052 [TPM2_PCR_SYSEXTS] = "sysexts",
5053 [TPM2_PCR_SHIM_POLICY] = "shim-policy",
5054 [TPM2_PCR_SYSTEM_IDENTITY] = "system-identity",
5055 [TPM2_PCR_DEBUG] = "debug",
5056 [TPM2_PCR_APPLICATION_SUPPORT] = "application-support",
96ead603
OJ
5057};
5058
2099cd62
LP
5059DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index, int, TPM2_PCRS_MAX - 1);
5060DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index, int);