]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/tpm2-util.c
Merge pull request #30971 from ddstreet/tpm2_key_conversion
[thirdparty/systemd.git] / src / shared / tpm2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <sys/file.h>
4
5 #include "alloc-util.h"
6 #include "constants.h"
7 #include "cryptsetup-util.h"
8 #include "dirent-util.h"
9 #include "dlfcn-util.h"
10 #include "efi-api.h"
11 #include "extract-word.h"
12 #include "fd-util.h"
13 #include "fileio.h"
14 #include "format-table.h"
15 #include "fs-util.h"
16 #include "hexdecoct.h"
17 #include "hmac.h"
18 #include "initrd-util.h"
19 #include "io-util.h"
20 #include "lock-util.h"
21 #include "log.h"
22 #include "logarithm.h"
23 #include "memory-util.h"
24 #include "mkdir.h"
25 #include "nulstr-util.h"
26 #include "parse-util.h"
27 #include "random-util.h"
28 #include "sha256.h"
29 #include "sort-util.h"
30 #include "stat-util.h"
31 #include "string-table.h"
32 #include "sync-util.h"
33 #include "time-util.h"
34 #include "tpm2-util.h"
35 #include "virt.h"
36
37 #if HAVE_TPM2
38 static void *libtss2_esys_dl = NULL;
39 static void *libtss2_rc_dl = NULL;
40 static void *libtss2_mu_dl = NULL;
41
42 static 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;
43 static 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;
44 static 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;
45 static 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;
46 static void (*sym_Esys_Finalize)(ESYS_CONTEXT **context) = NULL;
47 static TSS2_RC (*sym_Esys_FlushContext)(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) = NULL;
48 static void (*sym_Esys_Free)(void *ptr) = NULL;
49 static 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;
50 static TSS2_RC (*sym_Esys_GetRandom)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, UINT16 bytesRequested, TPM2B_DIGEST **randomBytes) = NULL;
51 static TSS2_RC (*sym_Esys_Import)(ESYS_CONTEXT *esysContext, ESYS_TR parentHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DATA *encryptionKey, const TPM2B_PUBLIC *objectPublic, const TPM2B_PRIVATE *duplicate, const TPM2B_ENCRYPTED_SECRET *inSymSeed, const TPMT_SYM_DEF_OBJECT *symmetricAlg, TPM2B_PRIVATE **outPrivate) = NULL;
52 static TSS2_RC (*sym_Esys_Initialize)(ESYS_CONTEXT **esys_context, TSS2_TCTI_CONTEXT *tcti, TSS2_ABI_VERSION *abiVersion) = NULL;
53 static 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;
54 static 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;
55 static TSS2_RC (*sym_Esys_NV_DefineSpace)(ESYS_CONTEXT *esysContext, ESYS_TR authHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_AUTH *auth, const TPM2B_NV_PUBLIC *publicInfo, ESYS_TR *nvHandle);
56 static TSS2_RC (*sym_Esys_NV_UndefineSpace)(ESYS_CONTEXT *esysContext, ESYS_TR authHandle, ESYS_TR nvIndex, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3);
57 static TSS2_RC (*sym_Esys_NV_Write)(ESYS_CONTEXT *esysContext, ESYS_TR authHandle, ESYS_TR nvIndex, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_MAX_NV_BUFFER *data, UINT16 offset);
58 static 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;
59 static 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;
60 static TSS2_RC (*sym_Esys_PolicyAuthValue)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) = NULL;
61 static 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;
62 static TSS2_RC (*sym_Esys_PolicyAuthorizeNV)(ESYS_CONTEXT *esysContext, ESYS_TR authHandle, ESYS_TR nvIndex, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3);
63 static TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) = NULL;
64 static TSS2_RC (*sym_Esys_PolicyOR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST *pHashList) = NULL;
65 static 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;
66 static 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;
67 static 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;
68 static TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL;
69 static TSS2_RC (*sym_Esys_TestParms)(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPMT_PUBLIC_PARMS *parameters) = NULL;
70 static TSS2_RC (*sym_Esys_TR_Close)(ESYS_CONTEXT *esys_context, ESYS_TR *rsrc_handle) = NULL;
71 static TSS2_RC (*sym_Esys_TR_Deserialize)(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle) = NULL;
72 static 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;
73 static TSS2_RC (*sym_Esys_TR_GetName)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name) = NULL;
74 static TSS2_RC (*sym_Esys_TR_GetTpmHandle)(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, TPM2_HANDLE *tpm_handle) = NULL;
75 static TSS2_RC (*sym_Esys_TR_Serialize)(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size) = NULL;
76 static TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL;
77 static TSS2_RC (*sym_Esys_TRSess_GetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION *flags) = NULL;
78 static TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask) = NULL;
79 static 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;
80 static 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;
81
82 static TSS2_RC (*sym_Tss2_MU_TPM2_CC_Marshal)(TPM2_CC src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
83 static TSS2_RC (*sym_Tss2_MU_TPM2_HANDLE_Marshal)(TPM2_HANDLE src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
84 static TSS2_RC (*sym_Tss2_MU_TPM2B_DIGEST_Marshal)(TPM2B_DIGEST const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
85 static TSS2_RC (*sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal)(TPM2B_ENCRYPTED_SECRET const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
86 static TSS2_RC (*sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_ENCRYPTED_SECRET *dest) = NULL;
87 static TSS2_RC (*sym_Tss2_MU_TPM2B_NAME_Marshal)(TPM2B_NAME const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
88 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Marshal)(TPM2B_PRIVATE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
89 static TSS2_RC (*sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PRIVATE *dest) = NULL;
90 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
91 static TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
92 static TSS2_RC (*sym_Tss2_MU_TPM2B_SENSITIVE_Marshal)(TPM2B_SENSITIVE const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
93 static 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;
94 static TSS2_RC (*sym_Tss2_MU_TPMS_NV_PUBLIC_Marshal)(TPMS_NV_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
95 static TSS2_RC (*sym_Tss2_MU_TPM2B_NV_PUBLIC_Marshal)(TPM2B_NV_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
96 static TSS2_RC (*sym_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_NV_PUBLIC *dest) = NULL;
97 static TSS2_RC (*sym_Tss2_MU_TPMS_ECC_POINT_Marshal)(TPMS_ECC_POINT const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
98 static TSS2_RC (*sym_Tss2_MU_TPMT_HA_Marshal)(TPMT_HA const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
99 static TSS2_RC (*sym_Tss2_MU_TPMT_PUBLIC_Marshal)(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
100 static TSS2_RC (*sym_Tss2_MU_UINT32_Marshal)(UINT32 src, uint8_t buffer[], size_t buffer_size, size_t *offset) = NULL;
101
102 static const char* (*sym_Tss2_RC_Decode)(TSS2_RC rc) = NULL;
103
104 int dlopen_tpm2(void) {
105 int r;
106
107 r = dlopen_many_sym_or_warn(
108 &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
109 DLSYM_ARG(Esys_Create),
110 DLSYM_ARG(Esys_CreateLoaded),
111 DLSYM_ARG(Esys_CreatePrimary),
112 DLSYM_ARG(Esys_EvictControl),
113 DLSYM_ARG(Esys_Finalize),
114 DLSYM_ARG(Esys_FlushContext),
115 DLSYM_ARG(Esys_Free),
116 DLSYM_ARG(Esys_GetCapability),
117 DLSYM_ARG(Esys_GetRandom),
118 DLSYM_ARG(Esys_Import),
119 DLSYM_ARG(Esys_Initialize),
120 DLSYM_ARG(Esys_Load),
121 DLSYM_ARG(Esys_LoadExternal),
122 DLSYM_ARG(Esys_NV_DefineSpace),
123 DLSYM_ARG(Esys_NV_UndefineSpace),
124 DLSYM_ARG(Esys_NV_Write),
125 DLSYM_ARG(Esys_PCR_Extend),
126 DLSYM_ARG(Esys_PCR_Read),
127 DLSYM_ARG(Esys_PolicyAuthValue),
128 DLSYM_ARG(Esys_PolicyAuthorize),
129 DLSYM_ARG(Esys_PolicyAuthorizeNV),
130 DLSYM_ARG(Esys_PolicyGetDigest),
131 DLSYM_ARG(Esys_PolicyOR),
132 DLSYM_ARG(Esys_PolicyPCR),
133 DLSYM_ARG(Esys_ReadPublic),
134 DLSYM_ARG(Esys_StartAuthSession),
135 DLSYM_ARG(Esys_Startup),
136 DLSYM_ARG(Esys_TestParms),
137 DLSYM_ARG(Esys_TR_Close),
138 DLSYM_ARG(Esys_TR_Deserialize),
139 DLSYM_ARG(Esys_TR_FromTPMPublic),
140 DLSYM_ARG(Esys_TR_GetName),
141 DLSYM_ARG(Esys_TR_Serialize),
142 DLSYM_ARG(Esys_TR_SetAuth),
143 DLSYM_ARG(Esys_TRSess_GetAttributes),
144 DLSYM_ARG(Esys_TRSess_SetAttributes),
145 DLSYM_ARG(Esys_Unseal),
146 DLSYM_ARG(Esys_VerifySignature));
147 if (r < 0)
148 return r;
149
150 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
151 * version of 2.4.0 this sym can be moved up to the normal list above. */
152 r = dlsym_many_or_warn(libtss2_esys_dl, LOG_DEBUG, DLSYM_ARG_FORCE(Esys_TR_GetTpmHandle));
153 if (r < 0)
154 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
155
156 r = dlopen_many_sym_or_warn(
157 &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
158 DLSYM_ARG(Tss2_RC_Decode));
159 if (r < 0)
160 return r;
161
162 return dlopen_many_sym_or_warn(
163 &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
164 DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
165 DLSYM_ARG(Tss2_MU_TPM2_HANDLE_Marshal),
166 DLSYM_ARG(Tss2_MU_TPM2B_DIGEST_Marshal),
167 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal),
168 DLSYM_ARG(Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal),
169 DLSYM_ARG(Tss2_MU_TPM2B_NAME_Marshal),
170 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
171 DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
172 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
173 DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
174 DLSYM_ARG(Tss2_MU_TPM2B_SENSITIVE_Marshal),
175 DLSYM_ARG(Tss2_MU_TPML_PCR_SELECTION_Marshal),
176 DLSYM_ARG(Tss2_MU_TPMS_NV_PUBLIC_Marshal),
177 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Marshal),
178 DLSYM_ARG(Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal),
179 DLSYM_ARG(Tss2_MU_TPMS_ECC_POINT_Marshal),
180 DLSYM_ARG(Tss2_MU_TPMT_HA_Marshal),
181 DLSYM_ARG(Tss2_MU_TPMT_PUBLIC_Marshal),
182 DLSYM_ARG(Tss2_MU_UINT32_Marshal));
183 }
184
185 void Esys_Freep(void *p) {
186 if (*(void**) p)
187 sym_Esys_Free(*(void**) p);
188 }
189
190 /* Get a specific TPM capability (or capabilities).
191 *
192 * Returns 0 if there are no more capability properties of the requested type, or 1 if there are more, or < 0
193 * on any error. Both 0 and 1 indicate this completed successfully, but do not indicate how many capability
194 * properties were provided in 'ret_capability_data'. To find the number of provided properties, check the
195 * specific type's 'count' field (e.g. for TPM2_CAP_ALGS, check ret_capability_data->algorithms.count).
196 *
197 * This calls TPM2_GetCapability() and does not alter the provided data, so it is important to understand how
198 * that TPM function works. It is recommended to check the TCG TPM specification Part 3 ("Commands") section
199 * on TPM2_GetCapability() for full details, but a short summary is: if this returns 0, all available
200 * properties have been provided in ret_capability_data, or no properties were available. If this returns 1,
201 * there are between 1 and "count" properties provided in ret_capability_data, and there are more available.
202 * Note that this may provide less than "count" properties even if the TPM has more available. Also, each
203 * capability category may have more specific requirements than described here; see the spec for exact
204 * details. */
205 static int tpm2_get_capability(
206 Tpm2Context *c,
207 TPM2_CAP capability,
208 uint32_t property,
209 uint32_t count,
210 TPMU_CAPABILITIES *ret_capability_data) {
211
212 _cleanup_(Esys_Freep) TPMS_CAPABILITY_DATA *capabilities = NULL;
213 TPMI_YES_NO more;
214 TSS2_RC rc;
215
216 assert(c);
217
218 log_debug("Getting TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " count %" PRIu32 ".",
219 capability, property, count);
220
221 rc = sym_Esys_GetCapability(
222 c->esys_context,
223 ESYS_TR_NONE,
224 ESYS_TR_NONE,
225 ESYS_TR_NONE,
226 capability,
227 property,
228 count,
229 &more,
230 &capabilities);
231 if (rc == TPM2_RC_VALUE)
232 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
233 "Requested TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 " apparently doesn't exist: %s",
234 capability, property, sym_Tss2_RC_Decode(rc));
235 if (rc != TSS2_RC_SUCCESS)
236 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
237 "Failed to get TPM2 capability 0x%04" PRIx32 " property 0x%04" PRIx32 ": %s",
238 capability, property, sym_Tss2_RC_Decode(rc));
239 if (capabilities->capability != capability)
240 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
241 "TPM provided wrong capability: 0x%04" PRIx32 " instead of 0x%04" PRIx32 ".",
242 capabilities->capability, capability);
243
244 if (ret_capability_data)
245 *ret_capability_data = capabilities->data;
246
247 return more == TPM2_YES;
248 }
249
250 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
251
252 static int tpm2_cache_capabilities(Tpm2Context *c) {
253 TPMU_CAPABILITIES capability;
254 int r;
255
256 assert(c);
257
258 /* Cache the algorithms. The spec indicates supported algorithms can only be modified during runtime
259 * by the SetAlgorithmSet() command. Unfortunately, the spec doesn't require a TPM reinitialization
260 * after changing the algorithm set (unless the PCR algorithms are changed). However, the spec also
261 * indicates the TPM behavior after SetAlgorithmSet() is "vendor-dependent", giving the example of
262 * flushing sessions and objects, erasing policies, etc. So, if the algorithm set is programmatically
263 * changed while we are performing some operation, it's reasonable to assume it will break us even if
264 * we don't cache the algorithms, thus they should be "safe" to cache. */
265 TPM2_ALG_ID current_alg = TPM2_ALG_FIRST;
266 for (;;) {
267 r = tpm2_get_capability(
268 c,
269 TPM2_CAP_ALGS,
270 (uint32_t) current_alg, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
271 TPM2_MAX_CAP_ALGS,
272 &capability);
273 if (r < 0)
274 return r;
275
276 TPML_ALG_PROPERTY algorithms = capability.algorithms;
277
278 /* We should never get 0; the TPM must support some algorithms, and it must not set 'more' if
279 * there are no more. */
280 assert(algorithms.count > 0);
281
282 if (!GREEDY_REALLOC_APPEND(
283 c->capability_algorithms,
284 c->n_capability_algorithms,
285 algorithms.algProperties,
286 algorithms.count))
287 return log_oom_debug();
288
289 if (r == 0)
290 break;
291
292 /* Set current_alg to alg id after last alg id the TPM provided */
293 current_alg = algorithms.algProperties[algorithms.count - 1].alg + 1;
294 }
295
296 /* Cache the command capabilities. The spec isn't actually clear if commands can be added/removed
297 * while running, but that would be crazy, so let's hope it is not possible. */
298 TPM2_CC current_cc = TPM2_CC_FIRST;
299 for (;;) {
300 r = tpm2_get_capability(
301 c,
302 TPM2_CAP_COMMANDS,
303 current_cc,
304 TPM2_MAX_CAP_CC,
305 &capability);
306 if (r < 0)
307 return r;
308
309 TPML_CCA commands = capability.command;
310
311 /* We should never get 0; the TPM must support some commands, and it must not set 'more' if
312 * there are no more. */
313 assert(commands.count > 0);
314
315 if (!GREEDY_REALLOC_APPEND(
316 c->capability_commands,
317 c->n_capability_commands,
318 commands.commandAttributes,
319 commands.count))
320 return log_oom_debug();
321
322 if (r == 0)
323 break;
324
325 /* Set current_cc to index after last cc the TPM provided */
326 current_cc = TPMA_CC_TO_TPM2_CC(commands.commandAttributes[commands.count - 1]) + 1;
327 }
328
329 /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
330 * while running, but that would be crazy, so let's hope it is not possible. */
331 TPM2_ECC_CURVE current_ecc_curve = TPM2_ECC_NONE;
332 for (;;) {
333 r = tpm2_get_capability(
334 c,
335 TPM2_CAP_ECC_CURVES,
336 current_ecc_curve,
337 TPM2_MAX_ECC_CURVES,
338 &capability);
339 if (r == -ENXIO) /* If the TPM doesn't support ECC, it might return TPM2_RC_VALUE rather than capability.eccCurves == 0 */
340 break;
341 if (r < 0)
342 return r;
343
344 TPML_ECC_CURVE ecc_curves = capability.eccCurves;
345
346 /* ECC support isn't required */
347 if (ecc_curves.count == 0)
348 break;
349
350 if (!GREEDY_REALLOC_APPEND(
351 c->capability_ecc_curves,
352 c->n_capability_ecc_curves,
353 ecc_curves.eccCurves,
354 ecc_curves.count))
355 return log_oom_debug();
356
357 if (r == 0)
358 break;
359
360 /* Set current_ecc_curve to index after last ecc curve the TPM provided */
361 current_ecc_curve = ecc_curves.eccCurves[ecc_curves.count - 1] + 1;
362 }
363
364 /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
365 * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
366 * reinitialized while we are using it, all our context and sessions will be invalid, so we can
367 * safely assume the TPM PCR allocation will not change while we are using it. */
368 r = tpm2_get_capability(
369 c,
370 TPM2_CAP_PCRS,
371 /* property= */ 0,
372 /* count= */ 1,
373 &capability);
374 if (r < 0)
375 return r;
376 if (r == 1)
377 /* This should never happen. Part 3 ("Commands") of the TCG TPM2 spec in the section for
378 * TPM2_GetCapability states: "TPM_CAP_PCRS – Returns the current allocation of PCR in a
379 * TPML_PCR_SELECTION. The property parameter shall be zero. The TPM will always respond to
380 * this command with the full PCR allocation and moreData will be NO." */
381 log_debug("TPM bug: reported multiple PCR sets; using only first set.");
382 c->capability_pcrs = capability.assignedPCR;
383
384 return 0;
385 }
386
387 /* Get the TPMA_ALGORITHM for a TPM2_ALG_ID. Returns true if the TPM supports the algorithm and the
388 * TPMA_ALGORITHM is provided, otherwise false. */
389 static bool tpm2_get_capability_alg(Tpm2Context *c, TPM2_ALG_ID alg, TPMA_ALGORITHM *ret) {
390 assert(c);
391
392 FOREACH_ARRAY(alg_prop, c->capability_algorithms, c->n_capability_algorithms)
393 if (alg_prop->alg == alg) {
394 if (ret)
395 *ret = alg_prop->algProperties;
396 return true;
397 }
398
399 log_debug("TPM does not support alg 0x%02" PRIx16 ".", alg);
400 if (ret)
401 *ret = 0;
402
403 return false;
404 }
405
406 bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg) {
407 return tpm2_get_capability_alg(c, alg, NULL);
408 }
409
410 /* Get the TPMA_CC for a TPM2_CC. Returns true if the TPM supports the command and the TPMA_CC is provided,
411 * otherwise false. */
412 static bool tpm2_get_capability_command(Tpm2Context *c, TPM2_CC command, TPMA_CC *ret) {
413 assert(c);
414
415 FOREACH_ARRAY(cca, c->capability_commands, c->n_capability_commands)
416 if (TPMA_CC_TO_TPM2_CC(*cca) == command) {
417 if (ret)
418 *ret = *cca;
419 return true;
420 }
421
422 log_debug("TPM does not support command 0x%04" PRIx32 ".", command);
423 if (ret)
424 *ret = 0;
425
426 return false;
427 }
428
429 bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command) {
430 return tpm2_get_capability_command(c, command, NULL);
431 }
432
433 /* Returns true if the TPM supports the ECC curve, otherwise false. */
434 bool tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE ecc_curve) {
435 assert(c);
436
437 FOREACH_ARRAY(curve, c->capability_ecc_curves, c->n_capability_ecc_curves)
438 if (*curve == ecc_curve)
439 return true;
440
441 log_debug("TPM does not support ECC curve 0x%" PRIx16 ".", ecc_curve);
442 return false;
443 }
444
445 /* Query the TPM for populated handles.
446 *
447 * This provides an array of handle indexes populated in the TPM, starting at the requested handle. The array will
448 * contain only populated handle addresses (which might not include the requested handle). The number of
449 * handles will be no more than the 'max' number requested. This will not search past the end of the handle
450 * range (i.e. handle & 0xff000000).
451 *
452 * Returns 0 if all populated handles in the range (starting at the requested handle) were provided (or no
453 * handles were in the range), or 1 if there are more populated handles in the range, or < 0 on any error. */
454 static int tpm2_get_capability_handles(
455 Tpm2Context *c,
456 TPM2_HANDLE start,
457 size_t max,
458 TPM2_HANDLE **ret_handles,
459 size_t *ret_n_handles) {
460
461 _cleanup_free_ TPM2_HANDLE *handles = NULL;
462 size_t n_handles = 0;
463 TPM2_HANDLE current = start;
464 int r = 0;
465
466 assert(c);
467 assert(ret_handles);
468 assert(ret_n_handles);
469
470 max = MIN(max, UINT32_MAX);
471
472 while (max > 0) {
473 TPMU_CAPABILITIES capability;
474 r = tpm2_get_capability(c, TPM2_CAP_HANDLES, current, (uint32_t) max, &capability);
475 if (r < 0)
476 return r;
477
478 TPML_HANDLE handle_list = capability.handles;
479 if (handle_list.count == 0)
480 break;
481
482 assert(handle_list.count <= max);
483
484 if (n_handles > SIZE_MAX - handle_list.count)
485 return log_oom_debug();
486
487 if (!GREEDY_REALLOC_APPEND(handles, n_handles, handle_list.handle, handle_list.count))
488 return log_oom_debug();
489
490 max -= handle_list.count;
491
492 /* Update current to the handle index after the last handle in the list. */
493 current = handles[n_handles - 1] + 1;
494
495 if (r == 0)
496 /* No more handles in this range. */
497 break;
498 }
499
500 *ret_handles = TAKE_PTR(handles);
501 *ret_n_handles = n_handles;
502
503 return r;
504 }
505
506 #define TPM2_HANDLE_RANGE(h) ((TPM2_HANDLE)((h) & TPM2_HR_RANGE_MASK))
507 #define TPM2_HANDLE_TYPE(h) ((TPM2_HT)(TPM2_HANDLE_RANGE(h) >> TPM2_HR_SHIFT))
508
509 /* Returns 1 if the handle is populated in the TPM, 0 if not, and < 0 on any error. */
510 static int tpm2_get_capability_handle(Tpm2Context *c, TPM2_HANDLE handle) {
511 _cleanup_free_ TPM2_HANDLE *handles = NULL;
512 size_t n_handles = 0;
513 int r;
514
515 r = tpm2_get_capability_handles(c, handle, 1, &handles, &n_handles);
516 if (r < 0)
517 return r;
518
519 return n_handles == 0 ? false : handles[0] == handle;
520 }
521
522 /* Returns 1 if the TPM supports the parms, or 0 if the TPM does not support the parms. */
523 bool tpm2_test_parms(Tpm2Context *c, TPMI_ALG_PUBLIC alg, const TPMU_PUBLIC_PARMS *parms) {
524 TSS2_RC rc;
525
526 assert(c);
527 assert(parms);
528
529 TPMT_PUBLIC_PARMS parameters = {
530 .type = alg,
531 .parameters = *parms,
532 };
533
534 rc = sym_Esys_TestParms(c->esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parameters);
535 if (rc != TSS2_RC_SUCCESS)
536 /* The spec says if the parms are not supported the TPM returns "...the appropriate
537 * unmarshaling error if a parameter is not valid". Since the spec (currently) defines 15
538 * unmarshaling errors, instead of checking for them all here, let's just assume any error
539 * indicates unsupported parms, and log the specific error text. */
540 log_debug("TPM does not support tested parms: %s", sym_Tss2_RC_Decode(rc));
541
542 return rc == TSS2_RC_SUCCESS;
543 }
544
545 static bool tpm2_supports_tpmt_public(Tpm2Context *c, const TPMT_PUBLIC *public) {
546 assert(c);
547 assert(public);
548
549 return tpm2_test_parms(c, public->type, &public->parameters);
550 }
551
552 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context *c, const TPMT_SYM_DEF_OBJECT *parameters) {
553 assert(c);
554 assert(parameters);
555
556 TPMU_PUBLIC_PARMS parms = {
557 .symDetail.sym = *parameters,
558 };
559
560 return tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms);
561 }
562
563 static bool tpm2_supports_tpmt_sym_def(Tpm2Context *c, const TPMT_SYM_DEF *parameters) {
564 assert(c);
565 assert(parameters);
566
567 /* Unfortunately, TPMT_SYM_DEF and TPMT_SYM_DEF_OBEJECT are separately defined, even though they are
568 * functionally identical. */
569 TPMT_SYM_DEF_OBJECT object = {
570 .algorithm = parameters->algorithm,
571 .keyBits = parameters->keyBits,
572 .mode = parameters->mode,
573 };
574
575 return tpm2_supports_tpmt_sym_def_object(c, &object);
576 }
577
578 static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
579 if (!c)
580 return NULL;
581
582 if (c->esys_context)
583 sym_Esys_Finalize(&c->esys_context);
584
585 c->tcti_context = mfree(c->tcti_context);
586 c->tcti_dl = safe_dlclose(c->tcti_dl);
587
588 c->capability_algorithms = mfree(c->capability_algorithms);
589 c->capability_commands = mfree(c->capability_commands);
590 c->capability_ecc_curves = mfree(c->capability_ecc_curves);
591
592 return mfree(c);
593 }
594
595 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context, tpm2_context, tpm2_context_free);
596
597 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB = {
598 .algorithm = TPM2_ALG_AES,
599 .keyBits.aes = 128,
600 .mode.aes = TPM2_ALG_CFB, /* The spec requires sessions to use CFB. */
601 };
602
603 int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
604 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = NULL;
605 TSS2_RC rc;
606 int r;
607
608 assert(ret_context);
609
610 context = new(Tpm2Context, 1);
611 if (!context)
612 return log_oom_debug();
613
614 *context = (Tpm2Context) {
615 .n_ref = 1,
616 };
617
618 r = dlopen_tpm2();
619 if (r < 0)
620 return log_debug_errno(r, "TPM2 support not installed: %m");
621
622 if (!device) {
623 device = secure_getenv("SYSTEMD_TPM2_DEVICE");
624 if (device)
625 /* Setting the env var to an empty string forces tpm2-tss' own device picking
626 * logic to be used. */
627 device = empty_to_null(device);
628 else
629 /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
630 * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
631 * might be used and we really don't want that, since it is a system service and that creates
632 * various ordering issues/deadlocks during early boot. */
633 device = "device:/dev/tpmrm0";
634 }
635
636 if (device) {
637 const char *param, *driver, *fn;
638 const TSS2_TCTI_INFO* info;
639 TSS2_TCTI_INFO_FUNC func;
640 size_t sz = 0;
641
642 param = strchr(device, ':');
643 if (param) {
644 /* Syntax #1: Pair of driver string and arbitrary parameter */
645 driver = strndupa_safe(device, param - device);
646 if (isempty(driver))
647 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
648
649 param++;
650 } else if (path_is_absolute(device) && path_is_valid(device)) {
651 /* Syntax #2: TPM device node */
652 driver = "device";
653 param = device;
654 } else
655 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
656
657 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
658
659 fn = strjoina("libtss2-tcti-", driver, ".so.0");
660
661 /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
662 if (!filename_is_valid(fn))
663 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
664
665 context->tcti_dl = dlopen(fn, RTLD_NOW);
666 if (!context->tcti_dl)
667 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());
668
669 func = dlsym(context->tcti_dl, TSS2_TCTI_INFO_SYMBOL);
670 if (!func)
671 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
672 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL ": %s",
673 dlerror());
674
675 info = func();
676 if (!info)
677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to get TCTI info data.");
678
679 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32 "]", info->name, info->description, info->version);
680
681 rc = info->init(NULL, &sz, NULL);
682 if (rc != TPM2_RC_SUCCESS)
683 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
684 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
685
686 context->tcti_context = malloc0(sz);
687 if (!context->tcti_context)
688 return log_oom_debug();
689
690 rc = info->init(context->tcti_context, &sz, param);
691 if (rc != TPM2_RC_SUCCESS)
692 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
693 "Failed to initialize TCTI context: %s", sym_Tss2_RC_Decode(rc));
694 }
695
696 rc = sym_Esys_Initialize(&context->esys_context, context->tcti_context, NULL);
697 if (rc != TSS2_RC_SUCCESS)
698 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
699 "Failed to initialize TPM context: %s", sym_Tss2_RC_Decode(rc));
700
701 rc = sym_Esys_Startup(context->esys_context, TPM2_SU_CLEAR);
702 if (rc == TPM2_RC_INITIALIZE)
703 log_debug("TPM already started up.");
704 else if (rc == TSS2_RC_SUCCESS)
705 log_debug("TPM successfully started up.");
706 else
707 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
708 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc));
709
710 r = tpm2_cache_capabilities(context);
711 if (r < 0)
712 return log_debug_errno(r, "Failed to cache TPM capabilities: %m");
713
714 /* We require AES and CFB support for session encryption. */
715 if (!tpm2_supports_alg(context, TPM2_ALG_AES))
716 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES.");
717
718 if (!tpm2_supports_alg(context, TPM2_ALG_CFB))
719 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support CFB.");
720
721 if (!tpm2_supports_tpmt_sym_def(context, &SESSION_TEMPLATE_SYM_AES_128_CFB))
722 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM does not support AES-128-CFB.");
723
724 *ret_context = TAKE_PTR(context);
725
726 return 0;
727 }
728
729 static void tpm2_handle_cleanup(ESYS_CONTEXT *esys_context, ESYS_TR esys_handle, bool flush) {
730 TSS2_RC rc;
731
732 if (!esys_context || esys_handle == ESYS_TR_NONE)
733 return;
734
735 /* Closing the handle removes its reference from the esys_context, but leaves the corresponding
736 * handle in the actual TPM. Flushing the handle removes its reference from the esys_context as well
737 * as removing its corresponding handle from the actual TPM. */
738 if (flush)
739 rc = sym_Esys_FlushContext(esys_context, esys_handle);
740 else
741 /* We can't use Esys_TR_Close() because the tpm2-tss library does not use reference counting
742 * for handles, and a single Esys_TR_Close() will remove the handle (internal to the tpm2-tss
743 * library) that might be in use by other code that is using the same ESYS_CONTEXT. This
744 * directly affects us; for example the src/test/test-tpm2.c test function
745 * check_seal_unseal() will encounter this issue and will result in a failure when trying to
746 * cleanup (i.e. Esys_FlushContext) the transient primary key that the test function
747 * generates. However, not calling Esys_TR_Close() here should be ok, since any leaked handle
748 * references will be cleaned up when we free our ESYS_CONTEXT.
749 *
750 * An upstream bug is open here: https://github.com/tpm2-software/tpm2-tss/issues/2693 */
751 rc = TSS2_RC_SUCCESS; // FIXME: restore sym_Esys_TR_Close() use once tpm2-tss is fixed and adopted widely enough
752 if (rc != TSS2_RC_SUCCESS)
753 /* We ignore failures here (besides debug logging), since this is called in error paths,
754 * where we cannot do anything about failures anymore. And when it is called in successful
755 * codepaths by this time we already did what we wanted to do, and got the results we wanted
756 * so there's no reason to make this fail more loudly than necessary. */
757 log_debug("Failed to %s TPM handle, ignoring: %s", flush ? "flush" : "close", sym_Tss2_RC_Decode(rc));
758 }
759
760 Tpm2Handle *tpm2_handle_free(Tpm2Handle *handle) {
761 if (!handle)
762 return NULL;
763
764 _cleanup_(tpm2_context_unrefp) Tpm2Context *context = (Tpm2Context*)handle->tpm2_context;
765 if (context)
766 tpm2_handle_cleanup(context->esys_context, handle->esys_handle, handle->flush);
767
768 return mfree(handle);
769 }
770
771 int tpm2_handle_new(Tpm2Context *context, Tpm2Handle **ret_handle) {
772 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
773
774 assert(ret_handle);
775
776 handle = new(Tpm2Handle, 1);
777 if (!handle)
778 return log_oom_debug();
779
780 *handle = (Tpm2Handle) {
781 .tpm2_context = tpm2_context_ref(context),
782 .esys_handle = ESYS_TR_NONE,
783 .flush = true,
784 };
785
786 *ret_handle = TAKE_PTR(handle);
787
788 return 0;
789 }
790
791 static int tpm2_read_public(
792 Tpm2Context *c,
793 const Tpm2Handle *session,
794 const Tpm2Handle *handle,
795 TPM2B_PUBLIC **ret_public,
796 TPM2B_NAME **ret_name,
797 TPM2B_NAME **ret_qname) {
798
799 TSS2_RC rc;
800
801 assert(c);
802 assert(handle);
803
804 rc = sym_Esys_ReadPublic(
805 c->esys_context,
806 handle->esys_handle,
807 session ? session->esys_handle : ESYS_TR_NONE,
808 ESYS_TR_NONE,
809 ESYS_TR_NONE,
810 ret_public,
811 ret_name,
812 ret_qname);
813 if (rc != TSS2_RC_SUCCESS)
814 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
815 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
816
817 return 0;
818 }
819
820 /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided.
821 * This should be used only for persistent, transient, or NV handles; and the handle must already exist in
822 * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the
823 * index is empty, or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent
824 * Tpm2Handle. */
825 int tpm2_index_to_handle(
826 Tpm2Context *c,
827 TPM2_HANDLE index,
828 const Tpm2Handle *session,
829 TPM2B_PUBLIC **ret_public,
830 TPM2B_NAME **ret_name,
831 TPM2B_NAME **ret_qname,
832 Tpm2Handle **ret_handle) {
833
834 TSS2_RC rc;
835 int r;
836
837 assert(c);
838
839 /* Only allow persistent, transient, or NV index handle types. */
840 switch (TPM2_HANDLE_TYPE(index)) {
841 case TPM2_HT_PERSISTENT:
842 case TPM2_HT_NV_INDEX:
843 case TPM2_HT_TRANSIENT:
844 break;
845 case TPM2_HT_PCR:
846 /* PCR handles are referenced by their actual index number and do not need a Tpm2Handle */
847 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
848 "Invalid handle 0x%08" PRIx32 " (in PCR range).", index);
849 case TPM2_HT_HMAC_SESSION:
850 case TPM2_HT_POLICY_SESSION:
851 /* Session indexes are only used internally by tpm2-tss (or lower code) */
852 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
853 "Invalid handle 0x%08" PRIx32 " (in session range).", index);
854 case TPM2_HT_PERMANENT:
855 /* Permanent handles are defined, e.g. ESYS_TR_RH_OWNER. */
856 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
857 "Invalid handle 0x%08" PRIx32 " (in permanent range).", index);
858 default:
859 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
860 "Invalid handle 0x%08" PRIx32 " (in unknown range).", index);
861 }
862
863 /* For transient handles, the kernel tpm "resource manager" (i.e. /dev/tpmrm0) performs mapping
864 * which breaks GetCapability requests, so only check GetCapability if it's not a transient handle.
865 * https://bugzilla.kernel.org/show_bug.cgi?id=218009 */
866 if (TPM2_HANDLE_TYPE(index) != TPM2_HT_TRANSIENT) { // FIXME: once kernel bug is fixed, check transient handles too
867 r = tpm2_get_capability_handle(c, index);
868 if (r < 0)
869 return r;
870 if (r == 0) {
871 log_debug("TPM handle 0x%08" PRIx32 " not populated.", index);
872 if (ret_public)
873 *ret_public = NULL;
874 if (ret_name)
875 *ret_name = NULL;
876 if (ret_qname)
877 *ret_qname = NULL;
878 if (ret_handle)
879 *ret_handle = NULL;
880 return 0;
881 }
882 }
883
884 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
885 r = tpm2_handle_new(c, &handle);
886 if (r < 0)
887 return r;
888
889 /* Since we didn't create this handle in the TPM (this is only creating an ESYS_TR handle for the
890 * pre-existing TPM handle), we shouldn't flush (or evict) it on cleanup. */
891 handle->flush = false;
892
893 rc = sym_Esys_TR_FromTPMPublic(
894 c->esys_context,
895 index,
896 session ? session->esys_handle : ESYS_TR_NONE,
897 ESYS_TR_NONE,
898 ESYS_TR_NONE,
899 &handle->esys_handle);
900 if (rc != TSS2_RC_SUCCESS)
901 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
902 "Failed to read public info: %s", sym_Tss2_RC_Decode(rc));
903
904 if (ret_public || ret_name || ret_qname) {
905 r = tpm2_read_public(c, session, handle, ret_public, ret_name, ret_qname);
906 if (r < 0)
907 return r;
908 }
909
910 if (ret_handle)
911 *ret_handle = TAKE_PTR(handle);
912
913 return 1;
914 }
915
916 /* Get the handle index for the provided Tpm2Handle. */
917 int tpm2_index_from_handle(Tpm2Context *c, const Tpm2Handle *handle, TPM2_HANDLE *ret_index) {
918 TSS2_RC rc;
919
920 assert(c);
921 assert(handle);
922 assert(ret_index);
923
924 /* Esys_TR_GetTpmHandle was added to tpm2-tss in version 2.4.0. Once we can set a minimum tpm2-tss
925 * version of 2.4.0 this check can be removed. */
926 if (!sym_Esys_TR_GetTpmHandle)
927 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
928 "libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
929
930 rc = sym_Esys_TR_GetTpmHandle(c->esys_context, handle->esys_handle, ret_index);
931 if (rc != TSS2_RC_SUCCESS)
932 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
933 "Failed to get handle index: %s", sym_Tss2_RC_Decode(rc));
934
935 return 0;
936 }
937
938 /* Copy an object in the TPM at a transient handle to a persistent handle.
939 *
940 * The provided transient handle must exist in the TPM in the transient range. The persistent handle may be 0
941 * or any handle in the persistent range. If 0, this will try each handle in the persistent range, in
942 * ascending order, until an available one is found. If non-zero, only the requested persistent handle will
943 * be used.
944 *
945 * Note that the persistent handle parameter is an handle index (i.e. number), while the transient handle is
946 * a Tpm2Handle object. The returned persistent handle will be a Tpm2Handle object that is located in the TPM
947 * at the requested persistent handle index (or the first available if none was requested).
948 *
949 * Returns 1 if the object was successfully persisted, or 0 if there is already a key at the requested
950 * handle, or < 0 on error. Theoretically, this would also return 0 if no specific persistent handle is
951 * requested but all persistent handles are used, but it is extremely unlikely the TPM has enough internal
952 * memory to store the entire persistent range, in which case an error will be returned if the TPM is out of
953 * memory for persistent storage. The persistent handle is only provided when returning 1. */
954 static int tpm2_persist_handle(
955 Tpm2Context *c,
956 const Tpm2Handle *transient_handle,
957 const Tpm2Handle *session,
958 TPMI_DH_PERSISTENT persistent_handle_index,
959 Tpm2Handle **ret_persistent_handle) {
960
961 /* We don't use TPM2_PERSISTENT_FIRST and TPM2_PERSISTENT_LAST here due to:
962 * https://github.com/systemd/systemd/pull/27713#issuecomment-1591864753 */
963 TPMI_DH_PERSISTENT first = UINT32_C(0x81000000), last = UINT32_C(0x81ffffff);
964 TSS2_RC rc;
965 int r;
966
967 assert(c);
968 assert(transient_handle);
969
970 /* If persistent handle index specified, only try that. */
971 if (persistent_handle_index != 0) {
972 if (TPM2_HANDLE_TYPE(persistent_handle_index) != TPM2_HT_PERSISTENT)
973 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
974 "Handle not in persistent range: 0x%x", persistent_handle_index);
975
976 first = last = persistent_handle_index;
977 }
978
979 for (TPMI_DH_PERSISTENT requested = first; requested <= last; requested++) {
980 _cleanup_(tpm2_handle_freep) Tpm2Handle *persistent_handle = NULL;
981 r = tpm2_handle_new(c, &persistent_handle);
982 if (r < 0)
983 return r;
984
985 /* Since this is a persistent handle, don't flush it. */
986 persistent_handle->flush = false;
987
988 rc = sym_Esys_EvictControl(
989 c->esys_context,
990 ESYS_TR_RH_OWNER,
991 transient_handle->esys_handle,
992 session ? session->esys_handle : ESYS_TR_PASSWORD,
993 ESYS_TR_NONE,
994 ESYS_TR_NONE,
995 requested,
996 &persistent_handle->esys_handle);
997 if (rc == TSS2_RC_SUCCESS) {
998 if (ret_persistent_handle)
999 *ret_persistent_handle = TAKE_PTR(persistent_handle);
1000
1001 return 1;
1002 }
1003 if (rc != TPM2_RC_NV_DEFINED)
1004 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1005 "Failed to persist handle: %s", sym_Tss2_RC_Decode(rc));
1006 }
1007
1008 if (ret_persistent_handle)
1009 *ret_persistent_handle = NULL;
1010
1011 return 0;
1012 }
1013
1014 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
1015
1016 static int tpm2_credit_random(Tpm2Context *c) {
1017 size_t rps, done = 0;
1018 TSS2_RC rc;
1019 usec_t t;
1020 int r;
1021
1022 assert(c);
1023
1024 /* Pulls some entropy from the TPM and adds it into the kernel RNG pool. That way we can say that the
1025 * key we will ultimately generate with the kernel random pool is at least as good as the TPM's RNG,
1026 * but likely better. Note that we don't trust the TPM RNG very much, hence do not actually credit
1027 * any entropy. */
1028
1029 if (access(TPM2_CREDIT_RANDOM_FLAG_PATH, F_OK) < 0) {
1030 if (errno != ENOENT)
1031 log_debug_errno(errno, "Failed to detect if '" TPM2_CREDIT_RANDOM_FLAG_PATH "' exists, ignoring: %m");
1032 } else {
1033 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
1034 return 0; /* Already done */
1035 }
1036
1037 t = now(CLOCK_MONOTONIC);
1038
1039 for (rps = random_pool_size(); rps > 0;) {
1040 _cleanup_(Esys_Freep) TPM2B_DIGEST *buffer = NULL;
1041
1042 rc = sym_Esys_GetRandom(
1043 c->esys_context,
1044 ESYS_TR_NONE,
1045 ESYS_TR_NONE,
1046 ESYS_TR_NONE,
1047 MIN(rps, 32U), /* 32 is supposedly a safe choice, given that AES 256bit keys are this long, and TPM2 baseline requires support for those. */
1048 &buffer);
1049 if (rc != TSS2_RC_SUCCESS)
1050 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1051 "Failed to acquire entropy from TPM: %s", sym_Tss2_RC_Decode(rc));
1052
1053 if (buffer->size == 0)
1054 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
1055 "Zero-sized entropy returned from TPM.");
1056
1057 r = random_write_entropy(-1, buffer->buffer, buffer->size, /* credit= */ false);
1058 if (r < 0)
1059 return log_debug_errno(r, "Failed wo write entropy to kernel: %m");
1060
1061 done += buffer->size;
1062 rps = LESS_BY(rps, buffer->size);
1063 }
1064
1065 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - t, 0));
1066
1067 r = touch(TPM2_CREDIT_RANDOM_FLAG_PATH);
1068 if (r < 0)
1069 log_debug_errno(r, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH "', ignoring: %m");
1070
1071 return 0;
1072 }
1073
1074 /* Get one of the legacy primary key templates.
1075 *
1076 * The legacy templates should only be used for older sealed data that did not use the SRK. Instead of a
1077 * persistent SRK, a transient key was created to seal the data and then flushed; and the exact same template
1078 * must be used to recreate the same transient key to unseal the data. The alg parameter must be TPM2_ALG_RSA
1079 * or TPM2_ALG_ECC. This does not check if the alg is actually supported on this TPM. */
1080 static int tpm2_get_legacy_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1081 /* Do not modify. */
1082 static const TPMT_PUBLIC legacy_ecc = {
1083 .type = TPM2_ALG_ECC,
1084 .nameAlg = TPM2_ALG_SHA256,
1085 .objectAttributes =
1086 TPMA_OBJECT_RESTRICTED|
1087 TPMA_OBJECT_DECRYPT|
1088 TPMA_OBJECT_FIXEDTPM|
1089 TPMA_OBJECT_FIXEDPARENT|
1090 TPMA_OBJECT_SENSITIVEDATAORIGIN|
1091 TPMA_OBJECT_USERWITHAUTH,
1092 .parameters.eccDetail = {
1093 .symmetric = {
1094 .algorithm = TPM2_ALG_AES,
1095 .keyBits.aes = 128,
1096 .mode.aes = TPM2_ALG_CFB,
1097 },
1098 .scheme.scheme = TPM2_ALG_NULL,
1099 .curveID = TPM2_ECC_NIST_P256,
1100 .kdf.scheme = TPM2_ALG_NULL,
1101 },
1102 };
1103
1104 /* Do not modify. */
1105 static const TPMT_PUBLIC legacy_rsa = {
1106 .type = TPM2_ALG_RSA,
1107 .nameAlg = TPM2_ALG_SHA256,
1108 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
1109 .parameters.rsaDetail = {
1110 .symmetric = {
1111 .algorithm = TPM2_ALG_AES,
1112 .keyBits.aes = 128,
1113 .mode.aes = TPM2_ALG_CFB,
1114 },
1115 .scheme.scheme = TPM2_ALG_NULL,
1116 .keyBits = 2048,
1117 },
1118 };
1119
1120 assert(ret_template);
1121
1122 if (alg == TPM2_ALG_ECC)
1123 *ret_template = legacy_ecc;
1124 else if (alg == TPM2_ALG_RSA)
1125 *ret_template = legacy_rsa;
1126 else
1127 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1128 "Unsupported legacy SRK alg: 0x%x", alg);
1129
1130 return 0;
1131 }
1132
1133 /* Get a Storage Root Key (SRK) template.
1134 *
1135 * The SRK template values are recommended by the "TCG TPM v2.0 Provisioning Guidance" document in section
1136 * 7.5.1 "Storage Primary Key (SRK) Templates", referencing "TCG EK Credential Profile for TPM Family 2.0".
1137 * The EK Credential Profile version 2.0 provides only a single template each for RSA and ECC, while later EK
1138 * Credential Profile versions provide more templates, and keep the original templates as "L-1" (for RSA) and
1139 * "L-2" (for ECC).
1140 *
1141 * https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance
1142 * https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile
1143 *
1144 * These templates are only needed to create a new persistent SRK (or a new transient key that is
1145 * SRK-compatible). Preferably, the TPM should contain a shared SRK located at the reserved shared SRK handle
1146 * (see TPM2_SRK_HANDLE in tpm2-util.h, and tpm2_get_srk() below).
1147 *
1148 * Returns 0 if the specified algorithm is ECC or RSA, otherwise -EOPNOTSUPP. */
1149 int tpm2_get_srk_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template) {
1150 /* The attributes are the same between ECC and RSA templates. This has the changes specified in the
1151 * Provisioning Guidance document, specifically:
1152 * TPMA_OBJECT_USERWITHAUTH is added.
1153 * TPMA_OBJECT_ADMINWITHPOLICY is removed.
1154 * TPMA_OBJECT_NODA is added. */
1155 TPMA_OBJECT srk_attributes =
1156 TPMA_OBJECT_DECRYPT |
1157 TPMA_OBJECT_FIXEDPARENT |
1158 TPMA_OBJECT_FIXEDTPM |
1159 TPMA_OBJECT_NODA |
1160 TPMA_OBJECT_RESTRICTED |
1161 TPMA_OBJECT_SENSITIVEDATAORIGIN |
1162 TPMA_OBJECT_USERWITHAUTH;
1163
1164 /* The symmetric configuration is the same between ECC and RSA templates. */
1165 TPMT_SYM_DEF_OBJECT srk_symmetric = {
1166 .algorithm = TPM2_ALG_AES,
1167 .keyBits.aes = 128,
1168 .mode.aes = TPM2_ALG_CFB,
1169 };
1170
1171 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
1172
1173 /* From the EK Credential Profile template "L-2". */
1174 TPMT_PUBLIC srk_ecc = {
1175 .type = TPM2_ALG_ECC,
1176 .nameAlg = TPM2_ALG_SHA256,
1177 .objectAttributes = srk_attributes,
1178 .parameters.eccDetail = {
1179 .symmetric = srk_symmetric,
1180 .scheme.scheme = TPM2_ALG_NULL,
1181 .curveID = TPM2_ECC_NIST_P256,
1182 .kdf.scheme = TPM2_ALG_NULL,
1183 },
1184 };
1185
1186 /* From the EK Credential Profile template "L-1". */
1187 TPMT_PUBLIC srk_rsa = {
1188 .type = TPM2_ALG_RSA,
1189 .nameAlg = TPM2_ALG_SHA256,
1190 .objectAttributes = srk_attributes,
1191 .parameters.rsaDetail = {
1192 .symmetric = srk_symmetric,
1193 .scheme.scheme = TPM2_ALG_NULL,
1194 .keyBits = 2048,
1195 },
1196 };
1197
1198 assert(ret_template);
1199
1200 switch (alg) {
1201 case TPM2_ALG_ECC:
1202 *ret_template = srk_ecc;
1203 return 0;
1204 case TPM2_ALG_RSA:
1205 *ret_template = srk_rsa;
1206 return 0;
1207 }
1208
1209 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "No SRK for algorithm 0x%" PRIx16, alg);
1210 }
1211
1212 /* Get the best supported SRK template. ECC is preferred, then RSA. */
1213 int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template) {
1214 TPMT_PUBLIC template;
1215 int r;
1216
1217 assert(c);
1218 assert(ret_template);
1219
1220 r = tpm2_get_srk_template(TPM2_ALG_ECC, &template);
1221 if (r < 0)
1222 return r;
1223
1224 if (!tpm2_supports_alg(c, TPM2_ALG_ECC))
1225 log_debug("TPM does not support ECC.");
1226 else if (!tpm2_supports_ecc_curve(c, template.parameters.eccDetail.curveID))
1227 log_debug("TPM does not support ECC-NIST-P256 curve.");
1228 else if (!tpm2_supports_tpmt_public(c, &template))
1229 log_debug("TPM does not support SRK ECC template L-2.");
1230 else {
1231 *ret_template = template;
1232 return 0;
1233 }
1234
1235 r = tpm2_get_srk_template(TPM2_ALG_RSA, &template);
1236 if (r < 0)
1237 return r;
1238
1239 if (!tpm2_supports_alg(c, TPM2_ALG_RSA))
1240 log_debug("TPM does not support RSA.");
1241 else if (!tpm2_supports_tpmt_public(c, &template))
1242 log_debug("TPM does not support SRK RSA template L-1.");
1243 else {
1244 *ret_template = template;
1245 return 0;
1246 }
1247
1248 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1249 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
1250 }
1251
1252 /* Get the SRK. Returns 1 if SRK is found, 0 if there is no SRK, or < 0 on error. Also see
1253 * tpm2_get_or_create_srk() below. */
1254 int tpm2_get_srk(
1255 Tpm2Context *c,
1256 const Tpm2Handle *session,
1257 TPM2B_PUBLIC **ret_public,
1258 TPM2B_NAME **ret_name,
1259 TPM2B_NAME **ret_qname,
1260 Tpm2Handle **ret_handle) {
1261
1262 return tpm2_index_to_handle(c, TPM2_SRK_HANDLE, session, ret_public, ret_name, ret_qname, ret_handle);
1263 }
1264
1265 /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already
1266 * exists, or < 0 on error. */
1267 int tpm2_get_or_create_srk(
1268 Tpm2Context *c,
1269 const Tpm2Handle *session,
1270 TPM2B_PUBLIC **ret_public,
1271 TPM2B_NAME **ret_name,
1272 TPM2B_NAME **ret_qname,
1273 Tpm2Handle **ret_handle) {
1274
1275 int r;
1276
1277 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1278 if (r < 0)
1279 return r;
1280 if (r == 1)
1281 return 0; /* 0 → SRK already set up */
1282
1283 /* No SRK, create and persist one */
1284 TPM2B_PUBLIC template = {
1285 .size = sizeof(TPMT_PUBLIC),
1286 };
1287 r = tpm2_get_best_srk_template(c, &template.publicArea);
1288 if (r < 0)
1289 return log_debug_errno(r, "Could not get best SRK template: %m");
1290
1291 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
1292 r = tpm2_create_primary(
1293 c,
1294 session,
1295 &template,
1296 /* sensitive= */ NULL,
1297 /* ret_public= */ NULL,
1298 &transient_handle);
1299 if (r < 0)
1300 return r;
1301
1302 /* Try to persist the transient SRK we created. No locking needed; if multiple threads are trying to
1303 * persist SRKs concurrently, only one will succeed (r == 1) while the rest will fail (r == 0). In
1304 * either case, all threads will get the persistent SRK below. */
1305 r = tpm2_persist_handle(c, transient_handle, session, TPM2_SRK_HANDLE, /* ret_persistent_handle= */ NULL);
1306 if (r < 0)
1307 return r;
1308
1309 /* The SRK should exist now. */
1310 r = tpm2_get_srk(c, session, ret_public, ret_name, ret_qname, ret_handle);
1311 if (r < 0)
1312 return r;
1313 if (r == 0)
1314 /* This should never happen. */
1315 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "SRK we just persisted couldn't be found.");
1316
1317 return 1; /* > 0 → SRK newly set up */
1318 }
1319
1320 /* Utility functions for TPMS_PCR_SELECTION. */
1321
1322 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1323 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION *s) {
1324 assert(s);
1325 assert(s->sizeofSelect <= sizeof(s->pcrSelect));
1326
1327 uint32_t mask = 0;
1328 for (unsigned i = 0; i < s->sizeofSelect; i++)
1329 SET_FLAG(mask, (uint32_t)s->pcrSelect[i] << (i * 8), true);
1330 return mask;
1331 }
1332
1333 /* Convert a mask and hash alg to a TPMS_PCR_SELECTION object. */
1334 void tpm2_tpms_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPMS_PCR_SELECTION *ret) {
1335 assert(ret);
1336
1337 /* This is currently hardcoded at 24 PCRs, above. */
1338 if (!TPM2_PCR_MASK_VALID(mask))
1339 log_debug("PCR mask selections (%x) out of range, ignoring.",
1340 mask & ~((uint32_t)TPM2_PCRS_MASK));
1341
1342 *ret = (TPMS_PCR_SELECTION){
1343 .hash = hash_alg,
1344 .sizeofSelect = TPM2_PCRS_MAX / 8,
1345 .pcrSelect[0] = mask & 0xff,
1346 .pcrSelect[1] = (mask >> 8) & 0xff,
1347 .pcrSelect[2] = (mask >> 16) & 0xff,
1348 };
1349 }
1350
1351 /* Test if all bits in the mask are set in the TPMS_PCR_SELECTION. */
1352 bool tpm2_tpms_pcr_selection_has_mask(const TPMS_PCR_SELECTION *s, uint32_t mask) {
1353 assert(s);
1354
1355 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s), mask);
1356 }
1357
1358 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION *s, uint32_t mask, bool b) {
1359 assert(s);
1360
1361 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s), mask, b), s->hash, s);
1362 }
1363
1364 /* Add all PCR selections in the mask. */
1365 void tpm2_tpms_pcr_selection_add_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1366 tpm2_tpms_pcr_selection_update_mask(s, mask, 1);
1367 }
1368
1369 /* Remove all PCR selections in the mask. */
1370 void tpm2_tpms_pcr_selection_sub_mask(TPMS_PCR_SELECTION *s, uint32_t mask) {
1371 tpm2_tpms_pcr_selection_update_mask(s, mask, 0);
1372 }
1373
1374 /* Add all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1375 void tpm2_tpms_pcr_selection_add(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1376 assert(a);
1377 assert(b);
1378 assert(a->hash == b->hash);
1379
1380 tpm2_tpms_pcr_selection_add_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1381 }
1382
1383 /* Remove all PCR selections in 'b' from 'a'. Both must have the same hash alg. */
1384 void tpm2_tpms_pcr_selection_sub(TPMS_PCR_SELECTION *a, const TPMS_PCR_SELECTION *b) {
1385 assert(a);
1386 assert(b);
1387 assert(a->hash == b->hash);
1388
1389 tpm2_tpms_pcr_selection_sub_mask(a, tpm2_tpms_pcr_selection_to_mask(b));
1390 }
1391
1392 /* Move all PCR selections in 'b' to 'a'. Both must have the same hash alg. */
1393 void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
1394 if (a == b)
1395 return;
1396
1397 tpm2_tpms_pcr_selection_add(a, b);
1398 tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
1399 }
1400
1401 #define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1402 _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
1403 #define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
1404 for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
1405 FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
1406
1407 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1408 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
1409
1410 #define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
1411 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
1412 FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
1413
1414 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION *s) {
1415 assert(s);
1416
1417 const char *algstr = strna(tpm2_hash_alg_to_string(s->hash));
1418
1419 _cleanup_free_ char *mask = tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s));
1420 if (!mask)
1421 return NULL;
1422
1423 return strjoin(algstr, "(", mask, ")");
1424 }
1425
1426 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION *s) {
1427 assert(s);
1428
1429 return popcount(tpm2_tpms_pcr_selection_to_mask(s));
1430 }
1431
1432 /* Utility functions for TPML_PCR_SELECTION. */
1433
1434 /* Remove the (0-based) index entry from 'l', shift all following entries, and update the count. */
1435 static void tpm2_tpml_pcr_selection_remove_index(TPML_PCR_SELECTION *l, uint32_t index) {
1436 assert(l);
1437 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1438 assert(index < l->count);
1439
1440 size_t s = l->count - (index + 1);
1441 memmove(&l->pcrSelections[index], &l->pcrSelections[index + 1], s * sizeof(l->pcrSelections[0]));
1442 l->count--;
1443 }
1444
1445 /* Get a TPMS_PCR_SELECTION from a TPML_PCR_SELECTION for the given hash alg. Returns NULL if there is no
1446 * entry for the hash alg. This guarantees the returned entry contains all the PCR selections for the given
1447 * hash alg, which may require modifying the TPML_PCR_SELECTION by removing duplicate entries. */
1448 static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
1449 TPML_PCR_SELECTION *l,
1450 TPMI_ALG_HASH hash_alg) {
1451
1452 assert(l);
1453 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1454
1455 TPMS_PCR_SELECTION *selection = NULL;
1456 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
1457 if (s->hash == hash_alg) {
1458 selection = s;
1459 break;
1460 }
1461
1462 if (!selection)
1463 return NULL;
1464
1465 /* Iterate backwards through the entries, removing any other entries for the hash alg. */
1466 for (uint32_t i = l->count - 1; i > 0; i--) {
1467 TPMS_PCR_SELECTION *s = &l->pcrSelections[i];
1468
1469 if (selection == s)
1470 break;
1471
1472 if (s->hash == hash_alg) {
1473 tpm2_tpms_pcr_selection_move(selection, s);
1474 tpm2_tpml_pcr_selection_remove_index(l, i);
1475 }
1476 }
1477
1478 return selection;
1479 }
1480
1481 /* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
1482 static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
1483 /* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
1484 for (uint32_t i = 0; i < l->count; i++)
1485 /* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
1486 (void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, l->pcrSelections[i].hash);
1487 }
1488
1489 /* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
1490 uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg) {
1491 assert(l);
1492
1493 /* Make a copy, as tpm2_tpml_pcr_selection_get_tpms_pcr_selection() will modify the object if there
1494 * are multiple entries with the requested hash alg. */
1495 TPML_PCR_SELECTION lcopy = *l;
1496
1497 TPMS_PCR_SELECTION *s;
1498 s = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy, hash_alg);
1499 if (!s)
1500 return 0;
1501
1502 return tpm2_tpms_pcr_selection_to_mask(s);
1503 }
1504
1505 /* Convert a mask and hash alg to a TPML_PCR_SELECTION object. */
1506 void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *ret) {
1507 assert(ret);
1508
1509 TPMS_PCR_SELECTION s;
1510 tpm2_tpms_pcr_selection_from_mask(mask, hash_alg, &s);
1511
1512 *ret = (TPML_PCR_SELECTION){
1513 .count = 1,
1514 .pcrSelections[0] = s,
1515 };
1516 }
1517
1518 /* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
1519 * TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
1520 * entries with the same hash alg. */
1521 void tpm2_tpml_pcr_selection_add_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1522 assert(l);
1523 assert(s);
1524
1525 if (tpm2_tpms_pcr_selection_is_empty(s))
1526 return;
1527
1528 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1529 if (selection) {
1530 tpm2_tpms_pcr_selection_add(selection, s);
1531 return;
1532 }
1533
1534 /* It's already broken if the count is higher than the array has size for. */
1535 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1536
1537 /* If full, the cleanup should result in at least one available entry. */
1538 if (l->count == ELEMENTSOF(l->pcrSelections))
1539 tpm2_tpml_pcr_selection_cleanup(l);
1540
1541 assert(l->count < ELEMENTSOF(l->pcrSelections));
1542 l->pcrSelections[l->count++] = *s;
1543 }
1544
1545 /* Remove the PCR selections in 's' from the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. This
1546 * will combine all entries for 's->hash' in 'l'. */
1547 void tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(TPML_PCR_SELECTION *l, const TPMS_PCR_SELECTION *s) {
1548 assert(l);
1549 assert(s);
1550
1551 if (tpm2_tpms_pcr_selection_is_empty(s))
1552 return;
1553
1554 TPMS_PCR_SELECTION *selection = tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
1555 if (selection)
1556 tpm2_tpms_pcr_selection_sub(selection, s);
1557 }
1558
1559 /* Test if all bits in the mask for the hash are set in the TPML_PCR_SELECTION. */
1560 bool tpm2_tpml_pcr_selection_has_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1561 assert(l);
1562
1563 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l, hash), mask);
1564 }
1565
1566 /* Add the PCR selections in the mask, with the provided hash. */
1567 void tpm2_tpml_pcr_selection_add_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1568 TPMS_PCR_SELECTION tpms;
1569
1570 assert(l);
1571
1572 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1573 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l, &tpms);
1574 }
1575
1576 /* Remove the PCR selections in the mask, with the provided hash. */
1577 void tpm2_tpml_pcr_selection_sub_mask(TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash, uint32_t mask) {
1578 TPMS_PCR_SELECTION tpms;
1579
1580 assert(l);
1581
1582 tpm2_tpms_pcr_selection_from_mask(mask, hash, &tpms);
1583 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l, &tpms);
1584 }
1585
1586 /* Add all PCR selections in 'b' to 'a'. */
1587 void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1588 assert(a);
1589 assert(b);
1590
1591 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1592 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
1593 }
1594
1595 /* Remove all PCR selections in 'b' from 'a'. */
1596 void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION *b) {
1597 assert(a);
1598 assert(b);
1599
1600 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
1601 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
1602 }
1603
1604 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
1605 assert(l);
1606
1607 _cleanup_free_ char *banks = NULL;
1608 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1609 if (tpm2_tpms_pcr_selection_is_empty(s))
1610 continue;
1611
1612 _cleanup_free_ char *str = tpm2_tpms_pcr_selection_to_string(s);
1613 if (!str || !strextend_with_separator(&banks, ",", str))
1614 return NULL;
1615 }
1616
1617 return strjoin("[", strempty(banks), "]");
1618 }
1619
1620 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION *l) {
1621 assert(l);
1622 assert(l->count <= ELEMENTSOF(l->pcrSelections));
1623
1624 size_t weight = 0;
1625 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
1626 size_t w = tpm2_tpms_pcr_selection_weight(s);
1627 assert(weight <= SIZE_MAX - w);
1628 weight += w;
1629 }
1630
1631 return weight;
1632 }
1633
1634 bool tpm2_pcr_value_valid(const Tpm2PCRValue *pcr_value) {
1635 int r;
1636
1637 if (!pcr_value)
1638 return false;
1639
1640 if (!TPM2_PCR_INDEX_VALID(pcr_value->index)) {
1641 log_debug("PCR index %u invalid.", pcr_value->index);
1642 return false;
1643 }
1644
1645 /* If it contains a value, the value size must match the hash size. */
1646 if (pcr_value->value.size > 0) {
1647 r = tpm2_hash_alg_to_size(pcr_value->hash);
1648 if (r < 0)
1649 return false;
1650
1651 if (pcr_value->value.size != (size_t) r) {
1652 log_debug("PCR hash 0x%" PRIx16 " expected size %d does not match actual size %" PRIu16 ".",
1653 pcr_value->hash, r, pcr_value->value.size);
1654 return false;
1655 }
1656 }
1657
1658 return true;
1659 }
1660
1661 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
1662 *
1663 * 1) all entries must be sorted in ascending order (e.g. using tpm2_sort_pcr_values())
1664 * 2) all entries must be unique, i.e. there cannot be 2 entries with the same hash and index
1665 *
1666 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1667 */
1668 bool tpm2_pcr_values_valid(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1669 if (!pcr_values && n_pcr_values > 0)
1670 return false;
1671
1672 const Tpm2PCRValue *previous = NULL;
1673 FOREACH_ARRAY(current, pcr_values, n_pcr_values) {
1674 if (!tpm2_pcr_value_valid(current))
1675 return false;
1676
1677 if (!previous) {
1678 previous = current;
1679 continue;
1680 }
1681
1682 /* Hashes must be sorted in ascending order */
1683 if (current->hash < previous->hash) {
1684 log_debug("PCR values not in ascending order, hash %" PRIu16 " is after %" PRIu16 ".",
1685 current->hash, previous->hash);
1686 return false;
1687 }
1688
1689 if (current->hash == previous->hash) {
1690 /* Indexes (for the same hash) must be sorted in ascending order */
1691 if (current->index < previous->index) {
1692 log_debug("PCR values not in ascending order, hash %" PRIu16 " index %u is after %u.",
1693 current->hash, current->index, previous->index);
1694 return false;
1695 }
1696
1697 /* Indexes (for the same hash) must not be duplicates */
1698 if (current->index == previous->index) {
1699 log_debug("PCR values contain duplicates for hash %" PRIu16 " index %u.",
1700 current->hash, previous->index);
1701 return false;
1702 }
1703 }
1704 }
1705
1706 return true;
1707 }
1708
1709 /* Returns true if any of the provided PCR values has an actual hash value included, false otherwise. */
1710 bool tpm2_pcr_values_has_any_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1711 assert(pcr_values || n_pcr_values == 0);
1712
1713 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1714 if (v->value.size > 0)
1715 return true;
1716
1717 return false;
1718 }
1719
1720 /* Returns true if all of the provided PCR values has an actual hash value included, false otherwise. */
1721 bool tpm2_pcr_values_has_all_values(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1722 assert(pcr_values || n_pcr_values == 0);
1723
1724 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1725 if (v->value.size == 0)
1726 return false;
1727
1728 return true;
1729 }
1730
1731 static int cmp_pcr_values(const Tpm2PCRValue *a, const Tpm2PCRValue *b) {
1732 assert(a);
1733 assert(b);
1734
1735 return CMP(a->hash, b->hash) ?: CMP(a->index, b->index);
1736 }
1737
1738 /* Sort the array of Tpm2PCRValue entries in-place. This sorts first in ascending order of hash algorithm
1739 * (sorting simply by the TPM2 hash algorithm number), and then sorting by pcr index. */
1740 void tpm2_sort_pcr_values(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1741 typesafe_qsort(pcr_values, n_pcr_values, cmp_pcr_values);
1742 }
1743
1744 int tpm2_pcr_values_from_mask(uint32_t mask, TPMI_ALG_HASH hash, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1745 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1746 size_t n_pcr_values = 0;
1747
1748 assert(ret_pcr_values);
1749 assert(ret_n_pcr_values);
1750
1751 FOREACH_PCR_IN_MASK(index, mask)
1752 if (!GREEDY_REALLOC_APPEND(
1753 pcr_values,
1754 n_pcr_values,
1755 &TPM2_PCR_VALUE_MAKE(index, hash, {}),
1756 1))
1757 return log_oom_debug();
1758
1759 *ret_pcr_values = TAKE_PTR(pcr_values);
1760 *ret_n_pcr_values = n_pcr_values;
1761
1762 return 0;
1763 }
1764
1765 int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPMI_ALG_HASH hash, uint32_t *ret_mask) {
1766 uint32_t mask = 0;
1767
1768 assert(pcr_values || n_pcr_values == 0);
1769 assert(ret_mask);
1770
1771 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1772 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PCR values.");
1773
1774 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
1775 if (v->hash == hash)
1776 SET_BIT(mask, v->index);
1777
1778 *ret_mask = mask;
1779
1780 return 0;
1781 }
1782
1783 int tpm2_tpml_pcr_selection_from_pcr_values(
1784 const Tpm2PCRValue *pcr_values,
1785 size_t n_pcr_values,
1786 TPML_PCR_SELECTION *ret_selection,
1787 TPM2B_DIGEST **ret_values,
1788 size_t *ret_n_values) {
1789
1790 TPML_PCR_SELECTION selection = {};
1791 _cleanup_free_ TPM2B_DIGEST *values = NULL;
1792 size_t n_values = 0;
1793
1794 assert(pcr_values || n_pcr_values == 0);
1795
1796 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
1797 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "PCR values are not valid.");
1798
1799 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1800 tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
1801
1802 if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
1803 return log_oom_debug();
1804 }
1805
1806 if (ret_selection)
1807 *ret_selection = selection;
1808 if (ret_values)
1809 *ret_values = TAKE_PTR(values);
1810 if (ret_n_values)
1811 *ret_n_values = n_values;
1812
1813 return 0;
1814 }
1815
1816 /* Count the number of different hash algorithms for all the entries. */
1817 int tpm2_pcr_values_hash_count(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, size_t *ret_count) {
1818 TPML_PCR_SELECTION selection;
1819 int r;
1820
1821 assert(pcr_values);
1822 assert(ret_count);
1823
1824 r = tpm2_tpml_pcr_selection_from_pcr_values(
1825 pcr_values,
1826 n_pcr_values,
1827 &selection,
1828 /* ret_values= */ NULL,
1829 /* ret_n_values= */ NULL);
1830 if (r < 0)
1831 return r;
1832
1833 *ret_count = selection.count;
1834
1835 return 0;
1836 }
1837
1838 /* Parse a string argument into a Tpm2PCRValue object.
1839 *
1840 * The format is <index>[:hash[=value]] where index is the index number (or name) of the PCR, e.g. 0 (or
1841 * platform-code), hash is the name of the hash algorithm (e.g. sha256) and value is the hex hash digest
1842 * value, optionally with a leading 0x. This does not check for validity of the fields. */
1843 int tpm2_pcr_value_from_string(const char *arg, Tpm2PCRValue *ret_pcr_value) {
1844 Tpm2PCRValue pcr_value = {};
1845 const char *p = arg;
1846 int r;
1847
1848 assert(arg);
1849 assert(ret_pcr_value);
1850
1851 _cleanup_free_ char *index = NULL;
1852 r = extract_first_word(&p, &index, ":", /* flags= */ 0);
1853 if (r < 1)
1854 return log_debug_errno(r, "Could not parse pcr value '%s': %m", p);
1855
1856 r = tpm2_pcr_index_from_string(index);
1857 if (r < 0)
1858 return log_debug_errno(r, "Invalid pcr index '%s': %m", index);
1859 pcr_value.index = (unsigned) r;
1860
1861 if (!isempty(p)) {
1862 _cleanup_free_ char *hash = NULL;
1863 r = extract_first_word(&p, &hash, "=", /* flags= */ 0);
1864 if (r < 1)
1865 return log_debug_errno(r, "Could not parse pcr hash algorithm '%s': %m", p);
1866
1867 r = tpm2_hash_alg_from_string(hash);
1868 if (r < 0)
1869 return log_debug_errno(r, "Invalid pcr hash algorithm '%s': %m", hash);
1870 pcr_value.hash = (TPMI_ALG_HASH) r;
1871
1872 if (!isempty(p)) {
1873 /* Remove leading 0x if present */
1874 p = startswith_no_case(p, "0x") ?: p;
1875
1876 _cleanup_free_ void *buf = NULL;
1877 size_t buf_size = 0;
1878 r = unhexmem(p, &buf, &buf_size);
1879 if (r < 0)
1880 return log_debug_errno(r, "Invalid pcr hash value '%s': %m", p);
1881
1882 r = TPM2B_DIGEST_CHECK_SIZE(buf_size);
1883 if (r < 0)
1884 return log_debug_errno(r, "PCR hash value size %zu too large.", buf_size);
1885
1886 pcr_value.value = TPM2B_DIGEST_MAKE(buf, buf_size);
1887 }
1888 }
1889
1890 *ret_pcr_value = pcr_value;
1891
1892 return 0;
1893 }
1894
1895 /* Return a string for the PCR value. The format is described in tpm2_pcr_value_from_string(). Note that if
1896 * the hash algorithm is not recognized, neither hash name nor hash digest value is included in the
1897 * string. This does not check for validity. */
1898 char *tpm2_pcr_value_to_string(const Tpm2PCRValue *pcr_value) {
1899 _cleanup_free_ char *index = NULL, *value = NULL;
1900
1901 if (asprintf(&index, "%u", pcr_value->index) < 0)
1902 return NULL;
1903
1904 const char *hash = pcr_value->hash > 0 ? tpm2_hash_alg_to_string(pcr_value->hash) : NULL;
1905
1906 if (hash && pcr_value->value.size > 0) {
1907 value = hexmem(pcr_value->value.buffer, pcr_value->value.size);
1908 if (!value)
1909 return NULL;
1910 }
1911
1912 return strjoin(index, hash ? ":" : "", strempty(hash), value ? "=" : "", strempty(value));
1913 }
1914
1915 /* Parse a string argument into an array of Tpm2PCRValue objects.
1916 *
1917 * The format is zero or more entries separated by ',' or '+'. The format of each entry is described in
1918 * tpm2_pcr_value_from_string(). This does not check for validity of the entries. */
1919 int tpm2_pcr_values_from_string(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
1920 const char *p = arg;
1921 int r;
1922
1923 assert(arg);
1924 assert(ret_pcr_values);
1925 assert(ret_n_pcr_values);
1926
1927 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
1928 size_t n_pcr_values = 0;
1929
1930 for (;;) {
1931 _cleanup_free_ char *pcr_arg = NULL;
1932 r = extract_first_word(&p, &pcr_arg, ",+", /* flags= */ 0);
1933 if (r < 0)
1934 return log_debug_errno(r, "Could not parse pcr values '%s': %m", p);
1935 if (r == 0)
1936 break;
1937
1938 Tpm2PCRValue pcr_value;
1939 r = tpm2_pcr_value_from_string(pcr_arg, &pcr_value);
1940 if (r < 0)
1941 return r;
1942
1943 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
1944 return log_oom_debug();
1945 }
1946
1947 *ret_pcr_values = TAKE_PTR(pcr_values);
1948 *ret_n_pcr_values = n_pcr_values;
1949
1950 return 0;
1951 }
1952
1953 /* Return a string representing the array of PCR values. The format is as described in
1954 * tpm2_pcr_values_from_string(). This does not check for validity. */
1955 char *tpm2_pcr_values_to_string(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
1956 _cleanup_free_ char *s = NULL;
1957
1958 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
1959 _cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(v);
1960 if (!pcrstr || !strextend_with_separator(&s, "+", pcrstr))
1961 return NULL;
1962 }
1963
1964 return s ? TAKE_PTR(s) : strdup("");
1965 }
1966
1967 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION *l, const char *msg) {
1968 if (!DEBUG_LOGGING || !l)
1969 return;
1970
1971 _cleanup_free_ char *s = tpm2_tpml_pcr_selection_to_string(l);
1972 log_debug("%s: %s", msg ?: "PCR selection", strna(s));
1973 }
1974
1975 void tpm2_log_debug_pcr_value(const Tpm2PCRValue *pcr_value, const char *msg) {
1976 if (!DEBUG_LOGGING || !pcr_value)
1977 return;
1978
1979 _cleanup_free_ char *s = tpm2_pcr_value_to_string(pcr_value);
1980 log_debug("%s: %s", msg ?: "PCR value", strna(s));
1981 }
1982
1983 void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
1984 if (!DEBUG_LOGGING || !buffer || size == 0)
1985 return;
1986
1987 _cleanup_free_ char *h = hexmem(buffer, size);
1988 log_debug("%s: %s", msg ?: "Buffer", strna(h));
1989 }
1990
1991 void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
1992 if (digest)
1993 tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
1994 }
1995
1996 void tpm2_log_debug_name(const TPM2B_NAME *name, const char *msg) {
1997 if (name)
1998 tpm2_log_debug_buffer(name->name, name->size, msg ?: "Name");
1999 }
2000
2001 static int tpm2_get_policy_digest(
2002 Tpm2Context *c,
2003 const Tpm2Handle *session,
2004 TPM2B_DIGEST **ret_policy_digest) {
2005
2006 TSS2_RC rc;
2007
2008 if (!DEBUG_LOGGING && !ret_policy_digest)
2009 return 0;
2010
2011 assert(c);
2012 assert(session);
2013
2014 log_debug("Acquiring policy digest.");
2015
2016 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
2017 rc = sym_Esys_PolicyGetDigest(
2018 c->esys_context,
2019 session->esys_handle,
2020 ESYS_TR_NONE,
2021 ESYS_TR_NONE,
2022 ESYS_TR_NONE,
2023 &policy_digest);
2024 if (rc != TSS2_RC_SUCCESS)
2025 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2026 "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
2027
2028 tpm2_log_debug_digest(policy_digest, "Session policy digest");
2029
2030 if (ret_policy_digest)
2031 *ret_policy_digest = TAKE_PTR(policy_digest);
2032
2033 return 0;
2034 }
2035
2036 int tpm2_create_primary(
2037 Tpm2Context *c,
2038 const Tpm2Handle *session,
2039 const TPM2B_PUBLIC *template,
2040 const TPM2B_SENSITIVE_CREATE *sensitive,
2041 TPM2B_PUBLIC **ret_public,
2042 Tpm2Handle **ret_handle) {
2043
2044 usec_t ts;
2045 TSS2_RC rc;
2046 int r;
2047
2048 assert(c);
2049 assert(template);
2050
2051 log_debug("Creating primary key on TPM.");
2052
2053 ts = now(CLOCK_MONOTONIC);
2054
2055 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2056 r = tpm2_handle_new(c, &handle);
2057 if (r < 0)
2058 return r;
2059
2060 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2061 rc = sym_Esys_CreatePrimary(
2062 c->esys_context,
2063 ESYS_TR_RH_OWNER,
2064 session ? session->esys_handle : ESYS_TR_PASSWORD,
2065 ESYS_TR_NONE,
2066 ESYS_TR_NONE,
2067 sensitive ?: &(TPM2B_SENSITIVE_CREATE) {},
2068 template,
2069 /* outsideInfo= */ NULL,
2070 &(TPML_PCR_SELECTION) {},
2071 &handle->esys_handle,
2072 &public,
2073 /* creationData= */ NULL,
2074 /* creationHash= */ NULL,
2075 /* creationTicket= */ NULL);
2076 if (rc != TSS2_RC_SUCCESS)
2077 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2078 "Failed to generate primary key in TPM: %s",
2079 sym_Tss2_RC_Decode(rc));
2080
2081 log_debug("Successfully created primary key on TPM in %s.",
2082 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2083
2084 if (ret_public)
2085 *ret_public = TAKE_PTR(public);
2086 if (ret_handle)
2087 *ret_handle = TAKE_PTR(handle);
2088
2089 return 0;
2090 }
2091
2092 /* Create a TPM object. Do not use this to create primary keys, because some HW TPMs refuse to allow that;
2093 * instead use tpm2_create_primary(). */
2094 int tpm2_create(Tpm2Context *c,
2095 const Tpm2Handle *parent,
2096 const Tpm2Handle *session,
2097 const TPMT_PUBLIC *template,
2098 const TPMS_SENSITIVE_CREATE *sensitive,
2099 TPM2B_PUBLIC **ret_public,
2100 TPM2B_PRIVATE **ret_private) {
2101
2102 usec_t ts;
2103 TSS2_RC rc;
2104
2105 assert(c);
2106 assert(parent);
2107 assert(template);
2108
2109 log_debug("Creating object on TPM.");
2110
2111 ts = now(CLOCK_MONOTONIC);
2112
2113 TPM2B_PUBLIC tpm2b_public = {
2114 .size = sizeof(*template) - sizeof(template->unique),
2115 .publicArea = *template,
2116 };
2117
2118 /* Zero the unique area. */
2119 zero(tpm2b_public.publicArea.unique);
2120
2121 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2122 if (sensitive)
2123 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2124 .size = sizeof(*sensitive),
2125 .sensitive = *sensitive,
2126 };
2127 else
2128 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2129
2130 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2131 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2132 rc = sym_Esys_Create(
2133 c->esys_context,
2134 parent->esys_handle,
2135 session ? session->esys_handle : ESYS_TR_PASSWORD,
2136 ESYS_TR_NONE,
2137 ESYS_TR_NONE,
2138 &tpm2b_sensitive,
2139 &tpm2b_public,
2140 /* outsideInfo= */ NULL,
2141 &(TPML_PCR_SELECTION) {},
2142 &private,
2143 &public,
2144 /* creationData= */ NULL,
2145 /* creationHash= */ NULL,
2146 /* creationTicket= */ NULL);
2147 if (rc != TSS2_RC_SUCCESS)
2148 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2149 "Failed to generate object in TPM: %s",
2150 sym_Tss2_RC_Decode(rc));
2151
2152 log_debug("Successfully created object on TPM in %s.",
2153 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2154
2155 if (ret_public)
2156 *ret_public = TAKE_PTR(public);
2157 if (ret_private)
2158 *ret_private = TAKE_PTR(private);
2159
2160 return 0;
2161 }
2162
2163 int tpm2_load(
2164 Tpm2Context *c,
2165 const Tpm2Handle *parent,
2166 const Tpm2Handle *session,
2167 const TPM2B_PUBLIC *public,
2168 const TPM2B_PRIVATE *private,
2169 Tpm2Handle **ret_handle) {
2170
2171 TSS2_RC rc;
2172 int r;
2173
2174 assert(c);
2175 assert(public);
2176 assert(private);
2177 assert(ret_handle);
2178
2179 log_debug("Loading object into TPM.");
2180
2181 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2182 r = tpm2_handle_new(c, &handle);
2183 if (r < 0)
2184 return r;
2185
2186 rc = sym_Esys_Load(
2187 c->esys_context,
2188 parent ? parent->esys_handle : ESYS_TR_RH_OWNER,
2189 session ? session->esys_handle : ESYS_TR_PASSWORD,
2190 ESYS_TR_NONE,
2191 ESYS_TR_NONE,
2192 private,
2193 public,
2194 &handle->esys_handle);
2195 if (rc == TPM2_RC_LOCKOUT)
2196 return log_debug_errno(SYNTHETIC_ERRNO(ENOLCK),
2197 "TPM2 device is in dictionary attack lockout mode.");
2198 if (rc != TSS2_RC_SUCCESS)
2199 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2200 "Failed to load key into TPM: %s", sym_Tss2_RC_Decode(rc));
2201
2202 *ret_handle = TAKE_PTR(handle);
2203
2204 return 0;
2205 }
2206
2207 static int tpm2_load_external(
2208 Tpm2Context *c,
2209 const Tpm2Handle *session,
2210 const TPM2B_PUBLIC *public,
2211 const TPM2B_SENSITIVE *private,
2212 Tpm2Handle **ret_handle) {
2213
2214 TSS2_RC rc;
2215 int r;
2216
2217 assert(c);
2218 assert(ret_handle);
2219
2220 log_debug("Loading external key into TPM.");
2221
2222 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2223 r = tpm2_handle_new(c, &handle);
2224 if (r < 0)
2225 return r;
2226
2227 rc = sym_Esys_LoadExternal(
2228 c->esys_context,
2229 session ? session->esys_handle : ESYS_TR_NONE,
2230 ESYS_TR_NONE,
2231 ESYS_TR_NONE,
2232 private,
2233 public,
2234 #if HAVE_TSS2_ESYS3
2235 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2236 * hierarchy, older versions need TPM2_RH_* instead. */
2237 ESYS_TR_RH_OWNER,
2238 #else
2239 TPM2_RH_OWNER,
2240 #endif
2241 &handle->esys_handle);
2242 if (rc != TSS2_RC_SUCCESS)
2243 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2244 "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
2245
2246 *ret_handle = TAKE_PTR(handle);
2247
2248 return 0;
2249 }
2250
2251 /* This calls TPM2_CreateLoaded() directly, without checking if the TPM supports it. Callers should instead
2252 * use tpm2_create_loaded(). */
2253 static int _tpm2_create_loaded(
2254 Tpm2Context *c,
2255 const Tpm2Handle *parent,
2256 const Tpm2Handle *session,
2257 const TPMT_PUBLIC *template,
2258 const TPMS_SENSITIVE_CREATE *sensitive,
2259 TPM2B_PUBLIC **ret_public,
2260 TPM2B_PRIVATE **ret_private,
2261 Tpm2Handle **ret_handle) {
2262
2263 usec_t ts;
2264 TSS2_RC rc;
2265 int r;
2266
2267 assert(c);
2268 assert(parent);
2269 assert(template);
2270
2271 log_debug("Creating loaded object on TPM.");
2272
2273 ts = now(CLOCK_MONOTONIC);
2274
2275 /* Copy the input template and zero the unique area. */
2276 TPMT_PUBLIC template_copy = *template;
2277 zero(template_copy.unique);
2278
2279 TPM2B_TEMPLATE tpm2b_template;
2280 size_t size = 0;
2281 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2282 &template_copy,
2283 tpm2b_template.buffer,
2284 sizeof(tpm2b_template.buffer),
2285 &size);
2286 if (rc != TSS2_RC_SUCCESS)
2287 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2288 "Failed to marshal public key template: %s", sym_Tss2_RC_Decode(rc));
2289 assert(size <= UINT16_MAX);
2290 tpm2b_template.size = size;
2291
2292 TPM2B_SENSITIVE_CREATE tpm2b_sensitive;
2293 if (sensitive)
2294 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {
2295 .size = sizeof(*sensitive),
2296 .sensitive = *sensitive,
2297 };
2298 else
2299 tpm2b_sensitive = (TPM2B_SENSITIVE_CREATE) {};
2300
2301 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2302 r = tpm2_handle_new(c, &handle);
2303 if (r < 0)
2304 return r;
2305
2306 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2307 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2308 rc = sym_Esys_CreateLoaded(
2309 c->esys_context,
2310 parent->esys_handle,
2311 session ? session->esys_handle : ESYS_TR_PASSWORD,
2312 ESYS_TR_NONE,
2313 ESYS_TR_NONE,
2314 &tpm2b_sensitive,
2315 &tpm2b_template,
2316 &handle->esys_handle,
2317 &private,
2318 &public);
2319 if (rc != TSS2_RC_SUCCESS)
2320 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2321 "Failed to generate loaded object in TPM: %s",
2322 sym_Tss2_RC_Decode(rc));
2323
2324 log_debug("Successfully created loaded object on TPM in %s.",
2325 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
2326
2327 if (ret_public)
2328 *ret_public = TAKE_PTR(public);
2329 if (ret_private)
2330 *ret_private = TAKE_PTR(private);
2331 if (ret_handle)
2332 *ret_handle = TAKE_PTR(handle);
2333
2334 return 0;
2335 }
2336
2337 /* This calls TPM2_CreateLoaded() if the TPM supports it, otherwise it calls TPM2_Create() and TPM2_Load()
2338 * separately. Do not use this to create primary keys, because some HW TPMs refuse to allow that; instead use
2339 * tpm2_create_primary(). */
2340 int tpm2_create_loaded(
2341 Tpm2Context *c,
2342 const Tpm2Handle *parent,
2343 const Tpm2Handle *session,
2344 const TPMT_PUBLIC *template,
2345 const TPMS_SENSITIVE_CREATE *sensitive,
2346 TPM2B_PUBLIC **ret_public,
2347 TPM2B_PRIVATE **ret_private,
2348 Tpm2Handle **ret_handle) {
2349
2350 int r;
2351
2352 if (tpm2_supports_command(c, TPM2_CC_CreateLoaded))
2353 return _tpm2_create_loaded(c, parent, session, template, sensitive, ret_public, ret_private, ret_handle);
2354
2355 /* Unfortunately, this TPM doesn't support CreateLoaded (added at spec revision 130) so we need to
2356 * create and load manually. */
2357 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
2358 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
2359 r = tpm2_create(c, parent, session, template, sensitive, &public, &private);
2360 if (r < 0)
2361 return r;
2362
2363 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
2364 r = tpm2_load(c, parent, session, public, private, &handle);
2365 if (r < 0)
2366 return r;
2367
2368 if (ret_public)
2369 *ret_public = TAKE_PTR(public);
2370 if (ret_private)
2371 *ret_private = TAKE_PTR(private);
2372 if (ret_handle)
2373 *ret_handle = TAKE_PTR(handle);
2374
2375 return 0;
2376 }
2377
2378 static int tpm2_marshal_private(const TPM2B_PRIVATE *private, void **ret, size_t *ret_size) {
2379 size_t max_size = sizeof(*private), blob_size = 0;
2380 _cleanup_free_ void *blob = NULL;
2381 TSS2_RC rc;
2382
2383 assert(private);
2384 assert(ret);
2385 assert(ret_size);
2386
2387 blob = malloc0(max_size);
2388 if (!blob)
2389 return log_oom_debug();
2390
2391 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
2392 if (rc != TSS2_RC_SUCCESS)
2393 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2394 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
2395
2396 *ret = TAKE_PTR(blob);
2397 *ret_size = blob_size;
2398 return 0;
2399 }
2400
2401 static int tpm2_unmarshal_private(const void *data, size_t size, TPM2B_PRIVATE *ret_private) {
2402 TPM2B_PRIVATE private = {};
2403 size_t offset = 0;
2404 TSS2_RC rc;
2405
2406 assert(data || size == 0);
2407 assert(ret_private);
2408
2409 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(data, size, &offset, &private);
2410 if (rc != TSS2_RC_SUCCESS)
2411 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2412 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
2413 if (offset != size)
2414 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2415 "Garbage at end of private key marshal data.");
2416
2417 *ret_private = private;
2418 return 0;
2419 }
2420
2421 int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size) {
2422 size_t max_size = sizeof(*public), blob_size = 0;
2423 _cleanup_free_ void *blob = NULL;
2424 TSS2_RC rc;
2425
2426 assert(public);
2427 assert(ret);
2428 assert(ret_size);
2429
2430 blob = malloc0(max_size);
2431 if (!blob)
2432 return log_oom_debug();
2433
2434 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
2435 if (rc != TSS2_RC_SUCCESS)
2436 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2437 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
2438
2439 *ret = TAKE_PTR(blob);
2440 *ret_size = blob_size;
2441 return 0;
2442 }
2443
2444 static int tpm2_unmarshal_public(const void *data, size_t size, TPM2B_PUBLIC *ret_public) {
2445 TPM2B_PUBLIC public = {};
2446 size_t offset = 0;
2447 TSS2_RC rc;
2448
2449 assert(data || size == 0);
2450 assert(ret_public);
2451
2452 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(data, size, &offset, &public);
2453 if (rc != TSS2_RC_SUCCESS)
2454 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2455 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
2456 if (offset != size)
2457 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2458 "Garbage at end of public key marshal data.");
2459
2460 *ret_public = public;
2461 return 0;
2462 }
2463
2464 int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC *nv_public, void **ret, size_t *ret_size) {
2465 size_t max_size = sizeof(*nv_public), blob_size = 0;
2466 _cleanup_free_ void *blob = NULL;
2467 TSS2_RC rc;
2468
2469 assert(nv_public);
2470 assert(ret);
2471 assert(ret_size);
2472
2473 blob = malloc0(max_size);
2474 if (!blob)
2475 return log_oom_debug();
2476
2477 rc = sym_Tss2_MU_TPM2B_NV_PUBLIC_Marshal(nv_public, blob, max_size, &blob_size);
2478 if (rc != TSS2_RC_SUCCESS)
2479 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2480 "Failed to marshal NV public structure: %s", sym_Tss2_RC_Decode(rc));
2481
2482 *ret = TAKE_PTR(blob);
2483 *ret_size = blob_size;
2484 return 0;
2485 }
2486
2487 int tpm2_unmarshal_nv_public(const void *data, size_t size, TPM2B_NV_PUBLIC *ret_nv_public) {
2488 TPM2B_NV_PUBLIC nv_public = {};
2489 size_t offset = 0;
2490 TSS2_RC rc;
2491
2492 assert(data || size == 0);
2493 assert(ret_nv_public);
2494
2495 rc = sym_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal(data, size, &offset, &nv_public);
2496 if (rc != TSS2_RC_SUCCESS)
2497 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2498 "Failed to unmarshal NV public structure: %s", sym_Tss2_RC_Decode(rc));
2499 if (offset != size)
2500 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2501 "Garbage at end of NV public structure marshal data.");
2502
2503 *ret_nv_public = nv_public;
2504 return 0;
2505 }
2506
2507 static int tpm2_import(
2508 Tpm2Context *c,
2509 const Tpm2Handle *parent,
2510 const Tpm2Handle *session,
2511 const TPM2B_PUBLIC *public,
2512 const TPM2B_PRIVATE *private,
2513 const TPM2B_ENCRYPTED_SECRET *seed,
2514 const TPM2B_DATA *encryption_key,
2515 const TPMT_SYM_DEF_OBJECT *symmetric,
2516 TPM2B_PRIVATE **ret_private) {
2517
2518 TSS2_RC rc;
2519
2520 assert(c);
2521 assert(parent);
2522 assert(!!encryption_key == !!symmetric);
2523 assert(public);
2524 assert(private);
2525 assert(seed);
2526 assert(ret_private);
2527
2528 log_debug("Importing key into TPM.");
2529
2530 rc = sym_Esys_Import(
2531 c->esys_context,
2532 parent->esys_handle,
2533 session ? session->esys_handle : ESYS_TR_PASSWORD,
2534 ESYS_TR_NONE,
2535 ESYS_TR_NONE,
2536 encryption_key,
2537 public,
2538 private,
2539 seed,
2540 symmetric ?: &(TPMT_SYM_DEF_OBJECT){ .algorithm = TPM2_ALG_NULL, },
2541 ret_private);
2542 if (rc != TSS2_RC_SUCCESS)
2543 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2544 "Failed to import key into TPM: %s", sym_Tss2_RC_Decode(rc));
2545
2546 return 0;
2547 }
2548
2549 /* Read hash values from the specified PCR selection. Provides a Tpm2PCRValue array that contains all
2550 * requested PCR values, in the order provided by the TPM. Normally, the provided pcr values will match
2551 * exactly what is in the provided selection, but the TPM may ignore some selected PCRs (for example, if an
2552 * unimplemented PCR index is requested), in which case those PCRs will be absent from the provided pcr
2553 * values. */
2554 int tpm2_pcr_read(
2555 Tpm2Context *c,
2556 const TPML_PCR_SELECTION *pcr_selection,
2557 Tpm2PCRValue **ret_pcr_values,
2558 size_t *ret_n_pcr_values) {
2559
2560 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2561 size_t n_pcr_values = 0;
2562 TSS2_RC rc;
2563
2564 assert(c);
2565 assert(pcr_selection);
2566 assert(ret_pcr_values);
2567 assert(ret_n_pcr_values);
2568
2569 TPML_PCR_SELECTION remaining = *pcr_selection;
2570 while (!tpm2_tpml_pcr_selection_is_empty(&remaining)) {
2571 _cleanup_(Esys_Freep) TPML_PCR_SELECTION *current_read = NULL;
2572 _cleanup_(Esys_Freep) TPML_DIGEST *current_values = NULL;
2573
2574 tpm2_log_debug_tpml_pcr_selection(&remaining, "Reading PCR selection");
2575
2576 /* Unfortunately, PCR_Read will not return more than 8 values. */
2577 rc = sym_Esys_PCR_Read(
2578 c->esys_context,
2579 ESYS_TR_NONE,
2580 ESYS_TR_NONE,
2581 ESYS_TR_NONE,
2582 &remaining,
2583 NULL,
2584 &current_read,
2585 &current_values);
2586 if (rc != TSS2_RC_SUCCESS)
2587 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2588 "Failed to read TPM2 PCRs: %s", sym_Tss2_RC_Decode(rc));
2589
2590 tpm2_log_debug_tpml_pcr_selection(current_read, "Read PCR selection");
2591
2592 if (tpm2_tpml_pcr_selection_is_empty(current_read)) {
2593 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2594 break;
2595 }
2596
2597 unsigned i = 0;
2598 FOREACH_PCR_IN_TPML_PCR_SELECTION(index, tpms, current_read) {
2599 assert(i < current_values->count);
2600 Tpm2PCRValue pcr_value = {
2601 .index = index,
2602 .hash = tpms->hash,
2603 .value = current_values->digests[i++],
2604 };
2605
2606 tpm2_log_debug_pcr_value(&pcr_value, /* msg= */ NULL);
2607
2608 if (!GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, &pcr_value, 1))
2609 return log_oom_debug();
2610 }
2611 assert(i == current_values->count);
2612
2613 tpm2_tpml_pcr_selection_sub(&remaining, current_read);
2614 }
2615
2616 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
2617
2618 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
2619 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PCR values read from TPM are not valid.");
2620
2621 *ret_pcr_values = TAKE_PTR(pcr_values);
2622 *ret_n_pcr_values = n_pcr_values;
2623
2624 return 0;
2625 }
2626
2627 /* Read the PCR value for each TPM2PCRValue entry in the array that does not have a value set. If all entries
2628 * have an unset hash (i.e. hash == 0), this first detects the "best" PCR bank to use; otherwise, all entries
2629 * must have a valid hash set. All entries must have a valid index. If this cannot read a PCR value for all
2630 * appropriate entries, this returns an error. This does not check the array for validity. */
2631 int tpm2_pcr_read_missing_values(Tpm2Context *c, Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
2632 TPMI_ALG_HASH pcr_bank = 0;
2633 int r;
2634
2635 assert(c);
2636 assert(pcr_values || n_pcr_values == 0);
2637
2638 if (n_pcr_values > 0) {
2639 size_t hash_count;
2640 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
2641 if (r < 0)
2642 return log_debug_errno(r, "Could not get hash count from pcr values: %m");
2643
2644 if (hash_count == 1 && pcr_values[0].hash == 0) {
2645 uint32_t mask;
2646 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, 0, &mask);
2647 if (r < 0)
2648 return r;
2649
2650 r = tpm2_get_best_pcr_bank(c, mask, &pcr_bank);
2651 if (r < 0)
2652 return r;
2653 }
2654 }
2655
2656 FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
2657 if (v->hash == 0)
2658 v->hash = pcr_bank;
2659
2660 if (v->value.size > 0)
2661 continue;
2662
2663 TPML_PCR_SELECTION selection;
2664 r = tpm2_tpml_pcr_selection_from_pcr_values(v, 1, &selection, NULL, NULL);
2665 if (r < 0)
2666 return r;
2667
2668 _cleanup_free_ Tpm2PCRValue *read_values = NULL;
2669 size_t n_read_values;
2670 r = tpm2_pcr_read(c, &selection, &read_values, &n_read_values);
2671 if (r < 0)
2672 return r;
2673
2674 if (n_read_values == 0)
2675 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
2676 "Could not read PCR hash 0x%" PRIu16 " index %u",
2677 v->hash, v->index);
2678
2679 assert(n_read_values == 1);
2680 assert(read_values[0].hash == v->hash);
2681 assert(read_values[0].index == v->index);
2682
2683 v->value = read_values[0].value;
2684 }
2685
2686 return 0;
2687 }
2688
2689 static int tpm2_pcr_mask_good(
2690 Tpm2Context *c,
2691 TPMI_ALG_HASH bank,
2692 uint32_t mask) {
2693
2694 TPML_PCR_SELECTION selection;
2695 int r;
2696
2697 assert(c);
2698
2699 /* So we have the problem that some systems might have working TPM2 chips, but the firmware doesn't
2700 * actually measure into them, or only into a suboptimal bank. If so, the PCRs should be all zero or
2701 * all 0xFF. Detect that, so that we can warn and maybe pick a better bank. */
2702
2703 tpm2_tpml_pcr_selection_from_mask(mask, bank, &selection);
2704
2705 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
2706 size_t n_pcr_values;
2707 r = tpm2_pcr_read(c, &selection, &pcr_values, &n_pcr_values);
2708 if (r < 0)
2709 return r;
2710
2711 /* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
2712 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
2713 if (!memeqbyte(0x00, v->value.buffer, v->value.size) &&
2714 !memeqbyte(0xFF, v->value.buffer, v->value.size))
2715 return true;
2716
2717 return false;
2718 }
2719
2720 static int tpm2_bank_has24(const TPMS_PCR_SELECTION *selection) {
2721
2722 assert(selection);
2723
2724 /* As per https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf a
2725 * TPM2 on a Client PC must have at least 24 PCRs. If this TPM has less, just skip over it. */
2726 if (selection->sizeofSelect < TPM2_PCRS_MAX/8) {
2727 log_debug("Skipping TPM2 PCR bank %s with fewer than 24 PCRs.",
2728 strna(tpm2_hash_alg_to_string(selection->hash)));
2729 return false;
2730 }
2731
2732 assert_cc(TPM2_PCRS_MAX % 8 == 0);
2733
2734 /* It's not enough to check how many PCRs there are, we also need to check that the 24 are
2735 * enabled for this bank. Otherwise this TPM doesn't qualify. */
2736 bool valid = true;
2737 for (size_t j = 0; j < TPM2_PCRS_MAX/8; j++)
2738 if (selection->pcrSelect[j] != 0xFF) {
2739 valid = false;
2740 break;
2741 }
2742
2743 if (!valid)
2744 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2745 strna(tpm2_hash_alg_to_string(selection->hash)));
2746
2747 return valid;
2748 }
2749
2750 int tpm2_get_best_pcr_bank(
2751 Tpm2Context *c,
2752 uint32_t pcr_mask,
2753 TPMI_ALG_HASH *ret) {
2754
2755 TPMI_ALG_HASH supported_hash = 0, hash_with_valid_pcr = 0;
2756 int r;
2757
2758 assert(c);
2759 assert(ret);
2760
2761 if (pcr_mask == 0) {
2762 log_debug("Asked to pick best PCR bank but no PCRs selected we could derive this from. Defaulting to SHA256.");
2763 *ret = TPM2_ALG_SHA256; /* if no PCRs are selected this doesn't matter anyway... */
2764 return 0;
2765 }
2766
2767 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2768 TPMI_ALG_HASH hash = selection->hash;
2769 int good;
2770
2771 /* For now we are only interested in the SHA1 and SHA256 banks */
2772 if (!IN_SET(hash, TPM2_ALG_SHA256, TPM2_ALG_SHA1))
2773 continue;
2774
2775 r = tpm2_bank_has24(selection);
2776 if (r < 0)
2777 return r;
2778 if (!r)
2779 continue;
2780
2781 good = tpm2_pcr_mask_good(c, hash, pcr_mask);
2782 if (good < 0)
2783 return good;
2784
2785 if (hash == TPM2_ALG_SHA256) {
2786 supported_hash = TPM2_ALG_SHA256;
2787 if (good) {
2788 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2789 hash_with_valid_pcr = TPM2_ALG_SHA256;
2790 break;
2791 }
2792 } else {
2793 assert(hash == TPM2_ALG_SHA1);
2794
2795 if (supported_hash == 0)
2796 supported_hash = TPM2_ALG_SHA1;
2797
2798 if (good && hash_with_valid_pcr == 0)
2799 hash_with_valid_pcr = TPM2_ALG_SHA1;
2800 }
2801 }
2802
2803 /* We preferably pick SHA256, but only if its PCRs are initialized or neither the SHA1 nor the SHA256
2804 * PCRs are initialized. If SHA256 is not supported but SHA1 is and its PCRs are too, we prefer
2805 * SHA1.
2806 *
2807 * We log at LOG_NOTICE level whenever we end up using the SHA1 bank or when the PCRs we bind to are
2808 * not initialized. */
2809
2810 if (hash_with_valid_pcr == TPM2_ALG_SHA256) {
2811 assert(supported_hash == TPM2_ALG_SHA256);
2812 log_debug("TPM2 device supports SHA256 PCR bank and SHA256 PCRs are valid, yay!");
2813 *ret = TPM2_ALG_SHA256;
2814 } else if (hash_with_valid_pcr == TPM2_ALG_SHA1) {
2815 if (supported_hash == TPM2_ALG_SHA256)
2816 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.");
2817 else {
2818 assert(supported_hash == TPM2_ALG_SHA1);
2819 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.");
2820 }
2821
2822 *ret = TPM2_ALG_SHA1;
2823 } else if (supported_hash == TPM2_ALG_SHA256) {
2824 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!");
2825 *ret = TPM2_ALG_SHA256;
2826 } else if (supported_hash == TPM2_ALG_SHA1) {
2827 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!");
2828 *ret = TPM2_ALG_SHA1;
2829 } else
2830 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2831 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2832
2833 return 0;
2834 }
2835
2836 int tpm2_get_good_pcr_banks(
2837 Tpm2Context *c,
2838 uint32_t pcr_mask,
2839 TPMI_ALG_HASH **ret) {
2840
2841 _cleanup_free_ TPMI_ALG_HASH *good_banks = NULL, *fallback_banks = NULL;
2842 size_t n_good_banks = 0, n_fallback_banks = 0;
2843 int r;
2844
2845 assert(c);
2846 assert(ret);
2847
2848 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection, &c->capability_pcrs) {
2849 TPMI_ALG_HASH hash = selection->hash;
2850
2851 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2852 r = tpm2_bank_has24(selection);
2853 if (r < 0)
2854 return r;
2855 if (!r)
2856 continue;
2857
2858 /* Let's now see if this bank has any of the selected PCRs actually initialized */
2859 r = tpm2_pcr_mask_good(c, hash, pcr_mask);
2860 if (r < 0)
2861 return r;
2862
2863 if (n_good_banks + n_fallback_banks >= INT_MAX)
2864 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many good TPM2 banks?");
2865
2866 if (r) {
2867 if (!GREEDY_REALLOC(good_banks, n_good_banks+1))
2868 return log_oom_debug();
2869
2870 good_banks[n_good_banks++] = hash;
2871 } else {
2872 if (!GREEDY_REALLOC(fallback_banks, n_fallback_banks+1))
2873 return log_oom_debug();
2874
2875 fallback_banks[n_fallback_banks++] = hash;
2876 }
2877 }
2878
2879 /* Preferably, use the good banks (i.e. the ones the PCR values are actually initialized so
2880 * far). Otherwise use the fallback banks (i.e. which exist and are enabled, but so far not used. */
2881 if (n_good_banks > 0) {
2882 log_debug("Found %zu fully initialized TPM2 banks.", n_good_banks);
2883 *ret = TAKE_PTR(good_banks);
2884 return (int) n_good_banks;
2885 }
2886 if (n_fallback_banks > 0) {
2887 log_debug("Found %zu enabled but un-initialized TPM2 banks.", n_fallback_banks);
2888 *ret = TAKE_PTR(fallback_banks);
2889 return (int) n_fallback_banks;
2890 }
2891
2892 /* No suitable banks found. */
2893 *ret = NULL;
2894 return 0;
2895 }
2896
2897 int tpm2_get_good_pcr_banks_strv(
2898 Tpm2Context *c,
2899 uint32_t pcr_mask,
2900 char ***ret) {
2901
2902 #if HAVE_OPENSSL
2903 _cleanup_free_ TPMI_ALG_HASH *algs = NULL;
2904 _cleanup_strv_free_ char **l = NULL;
2905 int n_algs;
2906
2907 assert(c);
2908 assert(ret);
2909
2910 n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs);
2911 if (n_algs < 0)
2912 return n_algs;
2913
2914 FOREACH_ARRAY(a, algs, n_algs) {
2915 _cleanup_free_ char *n = NULL;
2916 const EVP_MD *implementation;
2917 const char *salg;
2918
2919 salg = tpm2_hash_alg_to_string(*a);
2920 if (!salg)
2921 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
2922
2923 implementation = EVP_get_digestbyname(salg);
2924 if (!implementation)
2925 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure.");
2926
2927 n = strdup(ASSERT_PTR(EVP_MD_name(implementation)));
2928 if (!n)
2929 return log_oom_debug();
2930
2931 ascii_strlower(n); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2932
2933 if (strv_consume(&l, TAKE_PTR(n)) < 0)
2934 return log_oom_debug();
2935 }
2936
2937 *ret = TAKE_PTR(l);
2938 return 0;
2939 #else /* HAVE_OPENSSL */
2940 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
2941 #endif
2942 }
2943
2944 /* Hash data into the digest.
2945 *
2946 * If 'extend' is true, the hashing operation starts with the existing digest hash (and the digest is
2947 * required to have a hash and its size must be correct). If 'extend' is false, the digest size is
2948 * initialized to the correct size for 'alg' and the hashing operation does not include any existing digest
2949 * hash. If 'extend' is false and no data is provided, the digest is initialized to a zero digest.
2950 *
2951 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2952 * correct for 'alg'.
2953 *
2954 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2955 int tpm2_digest_many(
2956 TPMI_ALG_HASH alg,
2957 TPM2B_DIGEST *digest,
2958 const struct iovec data[],
2959 size_t n_data,
2960 bool extend) {
2961
2962 struct sha256_ctx ctx;
2963
2964 assert(digest);
2965 assert(data || n_data == 0);
2966
2967 if (alg != TPM2_ALG_SHA256)
2968 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2969 "Hash algorithm not supported: 0x%x", alg);
2970
2971 if (extend && digest->size != SHA256_DIGEST_SIZE)
2972 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2973 "Digest size 0x%x, require 0x%x",
2974 digest->size, (unsigned)SHA256_DIGEST_SIZE);
2975
2976 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2977 assert_cc(sizeof(digest->buffer) >= SHA256_DIGEST_SIZE);
2978
2979 CLEANUP_ERASE(ctx);
2980
2981 sha256_init_ctx(&ctx);
2982
2983 if (extend)
2984 sha256_process_bytes(digest->buffer, digest->size, &ctx);
2985 else {
2986 *digest = (TPM2B_DIGEST) {
2987 .size = SHA256_DIGEST_SIZE,
2988 };
2989 if (n_data == 0) /* If not extending and no data, return zero hash */
2990 return 0;
2991 }
2992
2993 FOREACH_ARRAY(d, data, n_data)
2994 sha256_process_bytes(d->iov_base, d->iov_len, &ctx);
2995
2996 sha256_finish_ctx(&ctx, digest->buffer);
2997
2998 return 0;
2999 }
3000
3001 /* Same as tpm2_digest_many() but data is contained in TPM2B_DIGEST[]. The digests may be any size digests. */
3002 int tpm2_digest_many_digests(
3003 TPMI_ALG_HASH alg,
3004 TPM2B_DIGEST *digest,
3005 const TPM2B_DIGEST data[],
3006 size_t n_data,
3007 bool extend) {
3008
3009 _cleanup_free_ struct iovec *iovecs = NULL;
3010
3011 assert(data || n_data == 0);
3012
3013 iovecs = new(struct iovec, n_data);
3014 if (!iovecs)
3015 return log_oom_debug();
3016
3017 for (size_t i = 0; i < n_data; i++)
3018 iovecs[i] = IOVEC_MAKE((void*) data[i].buffer, data[i].size);
3019
3020 return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
3021 }
3022
3023 /* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
3024 * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
3025 * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
3026 * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
3027 * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
3028 *
3029 * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
3030 * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
3031 * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
3032 * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
3033 *
3034 * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
3035 * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
3036 * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
3037 *
3038 * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
3039 * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
3040 * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
3041 * which we will trim the 0(s) from before sending to the TPM.
3042 */
3043 static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
3044 bool trimmed = false;
3045
3046 assert(auth);
3047
3048 while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
3049 trimmed = true;
3050 auth->size--;
3051 }
3052
3053 if (trimmed)
3054 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
3055 }
3056
3057 int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
3058 TPM2B_AUTH auth = {};
3059 int r;
3060
3061 assert(pin);
3062 assert(ret_auth);
3063
3064 r = tpm2_digest_buffer(hash, &auth, pin, strlen(pin), /* extend= */ false);
3065 if (r < 0)
3066 return r;
3067
3068 tpm2_trim_auth_value(&auth);
3069
3070 *ret_auth = TAKE_STRUCT(auth);
3071
3072 return 0;
3073 }
3074
3075 int tpm2_set_auth_binary(Tpm2Context *c, const Tpm2Handle *handle, const TPM2B_AUTH *auth) {
3076 TSS2_RC rc;
3077
3078 assert(c);
3079 assert(handle);
3080
3081 if (!auth)
3082 return 0;
3083
3084 rc = sym_Esys_TR_SetAuth(c->esys_context, handle->esys_handle, auth);
3085 if (rc != TSS2_RC_SUCCESS)
3086 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3087 "Failed to load PIN in TPM: %s", sym_Tss2_RC_Decode(rc));
3088
3089 return 0;
3090 }
3091
3092 int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
3093 TPM2B_AUTH auth = {};
3094 int r;
3095
3096 assert(c);
3097 assert(handle);
3098
3099 if (!pin)
3100 return 0;
3101
3102 CLEANUP_ERASE(auth);
3103
3104 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &auth);
3105 if (r < 0)
3106 return r;
3107
3108 return tpm2_set_auth_binary(c, handle, &auth);
3109 }
3110
3111 static bool tpm2_is_encryption_session(Tpm2Context *c, const Tpm2Handle *session) {
3112 TPMA_SESSION flags = 0;
3113 TSS2_RC rc;
3114
3115 assert(c);
3116 assert(session);
3117
3118 rc = sym_Esys_TRSess_GetAttributes(c->esys_context, session->esys_handle, &flags);
3119 if (rc != TSS2_RC_SUCCESS)
3120 return false;
3121
3122 return (flags & TPMA_SESSION_DECRYPT) && (flags & TPMA_SESSION_ENCRYPT);
3123 }
3124
3125 int tpm2_make_encryption_session(
3126 Tpm2Context *c,
3127 const Tpm2Handle *primary,
3128 const Tpm2Handle *bind_key,
3129 Tpm2Handle **ret_session) {
3130
3131 const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT |
3132 TPMA_SESSION_CONTINUESESSION;
3133 TSS2_RC rc;
3134 int r;
3135
3136 assert(c);
3137 assert(primary);
3138 assert(ret_session);
3139
3140 log_debug("Starting HMAC encryption session.");
3141
3142 /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which
3143 * means that the random salt will be encrypted with the well-known key. That way, only the TPM can
3144 * recover the salt, which is then used for key derivation. */
3145 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
3146 r = tpm2_handle_new(c, &session);
3147 if (r < 0)
3148 return r;
3149
3150 rc = sym_Esys_StartAuthSession(
3151 c->esys_context,
3152 primary->esys_handle,
3153 bind_key ? bind_key->esys_handle : ESYS_TR_NONE,
3154 ESYS_TR_NONE,
3155 ESYS_TR_NONE,
3156 ESYS_TR_NONE,
3157 NULL,
3158 TPM2_SE_HMAC,
3159 &SESSION_TEMPLATE_SYM_AES_128_CFB,
3160 TPM2_ALG_SHA256,
3161 &session->esys_handle);
3162 if (rc != TSS2_RC_SUCCESS)
3163 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3164 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
3165
3166 /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are
3167 * always used for sessions), this provides confidentiality, integrity and replay protection for
3168 * operations that use this session. */
3169 rc = sym_Esys_TRSess_SetAttributes(c->esys_context, session->esys_handle, sessionAttributes, 0xff);
3170 if (rc != TSS2_RC_SUCCESS)
3171 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3172 "Failed to configure TPM session: %s", sym_Tss2_RC_Decode(rc));
3173
3174 *ret_session = TAKE_PTR(session);
3175
3176 return 0;
3177 }
3178
3179 int tpm2_make_policy_session(
3180 Tpm2Context *c,
3181 const Tpm2Handle *primary,
3182 const Tpm2Handle *encryption_session,
3183 Tpm2Handle **ret_session) {
3184
3185 TSS2_RC rc;
3186 int r;
3187
3188 assert(c);
3189 assert(primary);
3190 assert(encryption_session);
3191 assert(ret_session);
3192
3193 if (!tpm2_is_encryption_session(c, encryption_session))
3194 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
3195 "Missing encryption session");
3196
3197 log_debug("Starting policy session.");
3198
3199 _cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
3200 r = tpm2_handle_new(c, &session);
3201 if (r < 0)
3202 return r;
3203
3204 rc = sym_Esys_StartAuthSession(
3205 c->esys_context,
3206 primary->esys_handle,
3207 ESYS_TR_NONE,
3208 encryption_session->esys_handle,
3209 ESYS_TR_NONE,
3210 ESYS_TR_NONE,
3211 NULL,
3212 TPM2_SE_POLICY,
3213 &SESSION_TEMPLATE_SYM_AES_128_CFB,
3214 TPM2_ALG_SHA256,
3215 &session->esys_handle);
3216 if (rc != TSS2_RC_SUCCESS)
3217 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3218 "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
3219
3220 *ret_session = TAKE_PTR(session);
3221
3222 return 0;
3223 }
3224
3225 static int find_signature(
3226 JsonVariant *v,
3227 const TPML_PCR_SELECTION *pcr_selection,
3228 const void *fp,
3229 size_t fp_size,
3230 const void *policy,
3231 size_t policy_size,
3232 void *ret_signature,
3233 size_t *ret_signature_size) {
3234
3235 #if HAVE_OPENSSL
3236 JsonVariant *b, *i;
3237 const char *k;
3238 int r;
3239
3240 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3241 * public key, and policy digest. */
3242
3243 if (!json_variant_is_object(v))
3244 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
3245
3246 uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
3247 uint32_t pcr_mask = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank);
3248
3249 k = tpm2_hash_alg_to_string(pcr_bank);
3250 if (!k)
3251 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
3252
3253 /* First, find field by bank */
3254 b = json_variant_by_key(v, k);
3255 if (!b)
3256 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
3257
3258 if (!json_variant_is_array(b))
3259 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
3260
3261 /* Now iterate through all signatures known for this bank */
3262 JSON_VARIANT_ARRAY_FOREACH(i, b) {
3263 _cleanup_free_ void *fpj_data = NULL, *polj_data = NULL;
3264 JsonVariant *maskj, *fpj, *sigj, *polj;
3265 size_t fpj_size, polj_size;
3266 uint32_t parsed_mask;
3267
3268 if (!json_variant_is_object(i))
3269 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data element is not a JSON object");
3270
3271 /* Check if the PCR mask matches our expectations */
3272 maskj = json_variant_by_key(i, "pcrs");
3273 if (!maskj)
3274 continue;
3275
3276 r = tpm2_parse_pcr_json_array(maskj, &parsed_mask);
3277 if (r < 0)
3278 return log_debug_errno(r, "Failed to parse JSON PCR mask");
3279
3280 if (parsed_mask != pcr_mask)
3281 continue; /* Not for this PCR mask */
3282
3283 /* Then check if this is for the public key we operate with */
3284 fpj = json_variant_by_key(i, "pkfp");
3285 if (!fpj)
3286 continue;
3287
3288 r = json_variant_unhex(fpj, &fpj_data, &fpj_size);
3289 if (r < 0)
3290 return log_debug_errno(r, "Failed to decode fingerprint in JSON data: %m");
3291
3292 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
3293 continue; /* Not for this public key */
3294
3295 /* Finally, check if this is for the PCR policy we expect this to be */
3296 polj = json_variant_by_key(i, "pol");
3297 if (!polj)
3298 continue;
3299
3300 r = json_variant_unhex(polj, &polj_data, &polj_size);
3301 if (r < 0)
3302 return log_debug_errno(r, "Failed to decode policy hash JSON data: %m");
3303
3304 if (memcmp_nn(policy, policy_size, polj_data, polj_size) != 0)
3305 continue;
3306
3307 /* This entry matches all our expectations, now return the signature included in it */
3308 sigj = json_variant_by_key(i, "sig");
3309 if (!sigj)
3310 continue;
3311
3312 return json_variant_unbase64(sigj, ret_signature, ret_signature_size);
3313 }
3314
3315 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
3316 #else /* HAVE_OPENSSL */
3317 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
3318 #endif
3319 }
3320
3321 /* Calculates the "name" of a public key.
3322 *
3323 * As specified in TPM2 spec "Part 1: Architecture", a key's "name" is its nameAlg value followed by a hash
3324 * of its TPM2 public area, all properly marshalled. This allows a key's "name" to be dependent not only on
3325 * the key fingerprint, but also on the TPM2-specific fields that associated with the key (i.e. all fields in
3326 * TPMT_PUBLIC). Note that this means an existing key may not change any of its TPMT_PUBLIC fields, since
3327 * that would also change the key name.
3328 *
3329 * Since we (currently) hardcode to always using SHA256 for hashing, this returns an error if the public key
3330 * nameAlg is not TPM2_ALG_SHA256. */
3331 int tpm2_calculate_pubkey_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name) {
3332 TSS2_RC rc;
3333 int r;
3334
3335 assert(public);
3336 assert(ret_name);
3337
3338 r = dlopen_tpm2();
3339 if (r < 0)
3340 return log_debug_errno(r, "TPM2 support not installed: %m");
3341
3342 if (public->nameAlg != TPM2_ALG_SHA256)
3343 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3344 "Unsupported nameAlg: 0x%x",
3345 public->nameAlg);
3346
3347 _cleanup_free_ uint8_t *buf = NULL;
3348 size_t size = 0;
3349
3350 buf = (uint8_t*) new(TPMT_PUBLIC, 1);
3351 if (!buf)
3352 return log_oom_debug();
3353
3354 rc = sym_Tss2_MU_TPMT_PUBLIC_Marshal(public, buf, sizeof(TPMT_PUBLIC), &size);
3355 if (rc != TSS2_RC_SUCCESS)
3356 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3357 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
3358
3359 TPM2B_DIGEST digest = {};
3360 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3361 if (r < 0)
3362 return r;
3363
3364 TPMT_HA ha = {
3365 .hashAlg = TPM2_ALG_SHA256,
3366 };
3367 assert(digest.size <= sizeof(ha.digest.sha256));
3368 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3369
3370 TPM2B_NAME name;
3371 size = 0;
3372 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3373 if (rc != TSS2_RC_SUCCESS)
3374 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3375 "Failed to marshal key name: %s", sym_Tss2_RC_Decode(rc));
3376 name.size = size;
3377
3378 tpm2_log_debug_name(&name, "Calculated public key name");
3379
3380 *ret_name = name;
3381
3382 return 0;
3383 }
3384
3385 /* Get the "name" of a key from the TPM.
3386 *
3387 * The "name" of a key is explained above in tpm2_calculate_pubkey_name().
3388 *
3389 * The handle must reference a key already present in the TPM. It may be either a public key only, or a
3390 * public/private keypair. */
3391 static int tpm2_get_name(
3392 Tpm2Context *c,
3393 const Tpm2Handle *handle,
3394 TPM2B_NAME **ret_name) {
3395
3396 _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL;
3397 TSS2_RC rc;
3398
3399 assert(c);
3400 assert(handle);
3401 assert(ret_name);
3402
3403 rc = sym_Esys_TR_GetName(c->esys_context, handle->esys_handle, &name);
3404 if (rc != TSS2_RC_SUCCESS)
3405 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3406 "Failed to get name of public key from TPM: %s", sym_Tss2_RC_Decode(rc));
3407
3408 tpm2_log_debug_name(name, "Object name");
3409
3410 *ret_name = TAKE_PTR(name);
3411
3412 return 0;
3413 }
3414
3415 int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC *nvpublic, TPM2B_NAME *ret_name) {
3416 TSS2_RC rc;
3417 int r;
3418
3419 assert(nvpublic);
3420 assert(ret_name);
3421
3422 r = dlopen_tpm2();
3423 if (r < 0)
3424 return log_debug_errno(r, "TPM2 support not installed: %m");
3425
3426 if (nvpublic->nameAlg != TPM2_ALG_SHA256)
3427 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3428 "Unsupported nameAlg: 0x%x",
3429 nvpublic->nameAlg);
3430
3431 _cleanup_free_ uint8_t *buf = NULL;
3432 size_t size = 0;
3433
3434 buf = (uint8_t*) new(TPMS_NV_PUBLIC, 1);
3435 if (!buf)
3436 return log_oom_debug();
3437
3438 rc = sym_Tss2_MU_TPMS_NV_PUBLIC_Marshal(nvpublic, buf, sizeof(TPMS_NV_PUBLIC), &size);
3439 if (rc != TSS2_RC_SUCCESS)
3440 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3441 "Failed to marshal NV index: %s", sym_Tss2_RC_Decode(rc));
3442
3443 TPM2B_DIGEST digest = {};
3444 r = tpm2_digest_buffer(TPM2_ALG_SHA256, &digest, buf, size, /* extend= */ false);
3445 if (r < 0)
3446 return r;
3447
3448 TPMT_HA ha = {
3449 .hashAlg = TPM2_ALG_SHA256,
3450 };
3451 assert(digest.size <= sizeof(ha.digest.sha256));
3452 memcpy_safe(ha.digest.sha256, digest.buffer, digest.size);
3453
3454 TPM2B_NAME name;
3455 size = 0;
3456 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, name.name, sizeof(name.name), &size);
3457 if (rc != TSS2_RC_SUCCESS)
3458 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3459 "Failed to marshal NV index name: %s", sym_Tss2_RC_Decode(rc));
3460 name.size = size;
3461
3462 tpm2_log_debug_name(&name, "Calculated NV index name");
3463
3464 *ret_name = name;
3465
3466 return 0;
3467 }
3468
3469 /* Extend 'digest' with the PolicyAuthValue calculated hash. */
3470 int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
3471 TPM2_CC command = TPM2_CC_PolicyAuthValue;
3472 TSS2_RC rc;
3473 int r;
3474
3475 assert(digest);
3476 assert(digest->size == SHA256_DIGEST_SIZE);
3477
3478 r = dlopen_tpm2();
3479 if (r < 0)
3480 return log_debug_errno(r, "TPM2 support not installed: %m");
3481
3482 uint8_t buf[sizeof(command)];
3483 size_t offset = 0;
3484
3485 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3486 if (rc != TSS2_RC_SUCCESS)
3487 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3488 "Failed to marshal PolicyAuthValue command: %s", sym_Tss2_RC_Decode(rc));
3489
3490 if (offset != sizeof(command))
3491 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3492 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset);
3493
3494 r = tpm2_digest_buffer(TPM2_ALG_SHA256, digest, buf, offset, /* extend= */ true);
3495 if (r < 0)
3496 return r;
3497
3498 tpm2_log_debug_digest(digest, "PolicyAuthValue calculated digest");
3499
3500 return 0;
3501 }
3502
3503 int tpm2_policy_auth_value(
3504 Tpm2Context *c,
3505 const Tpm2Handle *session,
3506 TPM2B_DIGEST **ret_policy_digest) {
3507
3508 TSS2_RC rc;
3509
3510 assert(c);
3511 assert(session);
3512
3513 log_debug("Submitting AuthValue policy.");
3514
3515 rc = sym_Esys_PolicyAuthValue(
3516 c->esys_context,
3517 session->esys_handle,
3518 ESYS_TR_NONE,
3519 ESYS_TR_NONE,
3520 ESYS_TR_NONE);
3521 if (rc != TSS2_RC_SUCCESS)
3522 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3523 "Failed to add authValue policy to TPM: %s",
3524 sym_Tss2_RC_Decode(rc));
3525
3526 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3527 }
3528
3529 int tpm2_calculate_policy_authorize_nv(
3530 const TPM2B_NV_PUBLIC *public_info,
3531 TPM2B_DIGEST *digest) {
3532 TPM2_CC command = TPM2_CC_PolicyAuthorizeNV;
3533 TSS2_RC rc;
3534 int r;
3535
3536 assert(public_info);
3537 assert(digest);
3538 assert(digest->size == SHA256_DIGEST_SIZE);
3539
3540 r = dlopen_tpm2();
3541 if (r < 0)
3542 return log_debug_errno(r, "TPM2 support not installed: %m");
3543
3544 uint8_t buf[sizeof(command)];
3545 size_t offset = 0;
3546
3547 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3548 if (rc != TSS2_RC_SUCCESS)
3549 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3550 "Failed to marshal PolicyAuthorizeNV command: %s", sym_Tss2_RC_Decode(rc));
3551
3552 if (offset != sizeof(command))
3553 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3554 "Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset);
3555
3556 TPM2B_NV_PUBLIC public_info_copy = *public_info; /* Make a copy, since we must set TPMA_NV_WRITTEN for the calculation */
3557 public_info_copy.nvPublic.attributes |= TPMA_NV_WRITTEN;
3558
3559 TPM2B_NAME name = {};
3560 r = tpm2_calculate_nv_index_name(&public_info_copy.nvPublic, &name);
3561 if (r < 0)
3562 return r;
3563
3564 struct iovec data[] = {
3565 IOVEC_MAKE(buf, offset),
3566 IOVEC_MAKE(name.name, name.size),
3567 };
3568
3569 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3570 if (r < 0)
3571 return r;
3572
3573 tpm2_log_debug_digest(digest, "PolicyAuthorizeNV calculated digest");
3574
3575 return 0;
3576 }
3577
3578 int tpm2_policy_authorize_nv(
3579 Tpm2Context *c,
3580 const Tpm2Handle *session,
3581 const Tpm2Handle *nv_handle,
3582 TPM2B_DIGEST **ret_policy_digest) {
3583
3584 TSS2_RC rc;
3585
3586 assert(c);
3587 assert(session);
3588
3589 log_debug("Submitting AuthorizeNV policy.");
3590
3591 rc = sym_Esys_PolicyAuthorizeNV(
3592 c->esys_context,
3593 ESYS_TR_RH_OWNER,
3594 nv_handle->esys_handle,
3595 session->esys_handle,
3596 ESYS_TR_PASSWORD,
3597 ESYS_TR_NONE,
3598 ESYS_TR_NONE);
3599 if (rc != TSS2_RC_SUCCESS)
3600 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3601 "Failed to add AuthorizeNV policy to TPM: %s",
3602 sym_Tss2_RC_Decode(rc));
3603
3604 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3605 }
3606
3607 int tpm2_policy_or(
3608 Tpm2Context *c,
3609 const Tpm2Handle *session,
3610 const TPM2B_DIGEST *branches, size_t n_branches,
3611 TPM2B_DIGEST **ret_policy_digest) {
3612
3613 TPML_DIGEST hash_list;
3614 TSS2_RC rc;
3615
3616 assert(c);
3617 assert(session);
3618
3619 if (n_branches > ELEMENTSOF(hash_list.digests))
3620 return -EOPNOTSUPP;
3621
3622 log_debug("Submitting OR policy.");
3623
3624 hash_list = (TPML_DIGEST) {
3625 .count = n_branches,
3626 };
3627
3628 memcpy(hash_list.digests, branches, n_branches * sizeof(TPM2B_DIGEST));
3629
3630 if (DEBUG_LOGGING)
3631 for (size_t i = 0; i < hash_list.count; i++) {
3632 _cleanup_free_ char *h = hexmem(hash_list.digests[i].buffer, hash_list.digests[i].size);
3633 log_debug("Submitting OR Branch #%zu: %s", i, h);
3634 }
3635
3636 rc = sym_Esys_PolicyOR(
3637 c->esys_context,
3638 session->esys_handle,
3639 ESYS_TR_NONE,
3640 ESYS_TR_NONE,
3641 ESYS_TR_NONE,
3642 &hash_list);
3643 if (rc != TSS2_RC_SUCCESS)
3644 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3645 "Failed to add OR policy to TPM: %s",
3646 sym_Tss2_RC_Decode(rc));
3647
3648 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3649 }
3650
3651 /* Extend 'digest' with the PolicyOR calculated hash. */
3652 int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TPM2B_DIGEST *digest) {
3653 TPM2_CC command = TPM2_CC_PolicyOR;
3654 TSS2_RC rc;
3655 int r;
3656
3657 assert(digest);
3658 assert(digest->size == SHA256_DIGEST_SIZE);
3659
3660 if (n_branches == 0)
3661 return -EINVAL;
3662 if (n_branches == 1)
3663 log_warning("PolicyOR with a single branch submitted, this is weird.");
3664 if (n_branches > 8)
3665 return -E2BIG;
3666
3667 r = dlopen_tpm2();
3668 if (r < 0)
3669 return log_error_errno(r, "TPM2 support not installed: %m");
3670
3671 uint8_t buf[sizeof(command)];
3672 size_t offset = 0;
3673
3674 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3675 if (rc != TSS2_RC_SUCCESS)
3676 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3677 "Failed to marshal PolicyOR command: %s", sym_Tss2_RC_Decode(rc));
3678
3679 if (offset != sizeof(command))
3680 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3681 "Offset 0x%zx wrong after marshalling PolicyOR command", offset);
3682 _cleanup_free_ struct iovec *data = new(struct iovec, 1 + n_branches);
3683 if (!data)
3684 return log_oom();
3685
3686 data[0] = IOVEC_MAKE(buf, offset);
3687 for (size_t i = 0; i < n_branches; i++) {
3688 data[1 + i] = IOVEC_MAKE((void*) branches[i].buffer, branches[i].size);
3689
3690 if (DEBUG_LOGGING) {
3691 _cleanup_free_ char *h = hexmem(branches[i].buffer, branches[i].size);
3692 log_debug("OR Branch #%zu: %s", i, h);
3693 }
3694 }
3695
3696 /* PolicyOR does not use the previous hash value; we must zero and then extend it. */
3697 zero(digest->buffer);
3698
3699 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, 1 + n_branches, /* extend= */ true);
3700 if (r < 0)
3701 return r;
3702
3703 tpm2_log_debug_digest(digest, "PolicyOR calculated digest");
3704
3705 return 0;
3706 }
3707
3708 /* Extend 'digest' with the PolicyPCR calculated hash. */
3709 int tpm2_calculate_policy_pcr(
3710 const Tpm2PCRValue *pcr_values,
3711 size_t n_pcr_values,
3712 TPM2B_DIGEST *digest) {
3713
3714 TPM2_CC command = TPM2_CC_PolicyPCR;
3715 TSS2_RC rc;
3716 int r;
3717
3718 assert(pcr_values || n_pcr_values == 0);
3719 assert(digest);
3720 assert(digest->size == SHA256_DIGEST_SIZE);
3721
3722 r = dlopen_tpm2();
3723 if (r < 0)
3724 return log_debug_errno(r, "TPM2 support not installed: %m");
3725
3726 TPML_PCR_SELECTION pcr_selection;
3727 _cleanup_free_ TPM2B_DIGEST *values = NULL;
3728 size_t n_values;
3729 r = tpm2_tpml_pcr_selection_from_pcr_values(pcr_values, n_pcr_values, &pcr_selection, &values, &n_values);
3730 if (r < 0)
3731 return log_debug_errno(r, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3732
3733 TPM2B_DIGEST hash = {};
3734 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, &hash, values, n_values, /* extend= */ false);
3735 if (r < 0)
3736 return r;
3737
3738 _cleanup_free_ uint8_t *buf = NULL;
3739 size_t size = 0, maxsize = sizeof(command) + sizeof(pcr_selection);
3740
3741 buf = malloc(maxsize);
3742 if (!buf)
3743 return log_oom_debug();
3744
3745 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, maxsize, &size);
3746 if (rc != TSS2_RC_SUCCESS)
3747 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3748 "Failed to marshal PolicyPCR command: %s", sym_Tss2_RC_Decode(rc));
3749
3750 rc = sym_Tss2_MU_TPML_PCR_SELECTION_Marshal(&pcr_selection, buf, maxsize, &size);
3751 if (rc != TSS2_RC_SUCCESS)
3752 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3753 "Failed to marshal PCR selection: %s", sym_Tss2_RC_Decode(rc));
3754
3755 struct iovec data[] = {
3756 IOVEC_MAKE(buf, size),
3757 IOVEC_MAKE(hash.buffer, hash.size),
3758 };
3759 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3760 if (r < 0)
3761 return r;
3762
3763 tpm2_log_debug_digest(digest, "PolicyPCR calculated digest");
3764
3765 return 0;
3766 }
3767
3768 int tpm2_policy_pcr(
3769 Tpm2Context *c,
3770 const Tpm2Handle *session,
3771 const TPML_PCR_SELECTION *pcr_selection,
3772 TPM2B_DIGEST **ret_policy_digest) {
3773
3774 TSS2_RC rc;
3775
3776 assert(c);
3777 assert(session);
3778 assert(pcr_selection);
3779
3780 log_debug("Submitting PCR hash policy.");
3781
3782 rc = sym_Esys_PolicyPCR(
3783 c->esys_context,
3784 session->esys_handle,
3785 ESYS_TR_NONE,
3786 ESYS_TR_NONE,
3787 ESYS_TR_NONE,
3788 NULL,
3789 pcr_selection);
3790 if (rc != TSS2_RC_SUCCESS)
3791 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3792 "Failed to add PCR policy to TPM: %s", sym_Tss2_RC_Decode(rc));
3793
3794 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3795 }
3796
3797 /* Extend 'digest' with the PolicyAuthorize calculated hash. */
3798 int tpm2_calculate_policy_authorize(
3799 const TPM2B_PUBLIC *public,
3800 const TPM2B_DIGEST *policy_ref,
3801 TPM2B_DIGEST *digest) {
3802
3803 TPM2_CC command = TPM2_CC_PolicyAuthorize;
3804 TSS2_RC rc;
3805 int r;
3806
3807 assert(public);
3808 assert(digest);
3809 assert(digest->size == SHA256_DIGEST_SIZE);
3810
3811 r = dlopen_tpm2();
3812 if (r < 0)
3813 return log_debug_errno(r, "TPM2 support not installed: %m");
3814
3815 uint8_t buf[sizeof(command)];
3816 size_t offset = 0;
3817
3818 rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
3819 if (rc != TSS2_RC_SUCCESS)
3820 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3821 "Failed to marshal PolicyAuthorize command: %s", sym_Tss2_RC_Decode(rc));
3822
3823 if (offset != sizeof(command))
3824 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3825 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset);
3826
3827 TPM2B_NAME name = {};
3828 r = tpm2_calculate_pubkey_name(&public->publicArea, &name);
3829 if (r < 0)
3830 return r;
3831
3832 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3833 zero(digest->buffer);
3834
3835 struct iovec data[] = {
3836 IOVEC_MAKE(buf, offset),
3837 IOVEC_MAKE(name.name, name.size),
3838 };
3839 r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
3840 if (r < 0)
3841 return r;
3842
3843 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3844 if (policy_ref)
3845 r = tpm2_digest_many_digests(TPM2_ALG_SHA256, digest, policy_ref, 1, /* extend= */ true);
3846 else
3847 r = tpm2_digest_rehash(TPM2_ALG_SHA256, digest);
3848 if (r < 0)
3849 return r;
3850
3851 tpm2_log_debug_digest(digest, "PolicyAuthorize calculated digest");
3852
3853 return 0;
3854 }
3855
3856 static int tpm2_policy_authorize(
3857 Tpm2Context *c,
3858 const Tpm2Handle *session,
3859 TPML_PCR_SELECTION *pcr_selection,
3860 const TPM2B_PUBLIC *public,
3861 const void *fp,
3862 size_t fp_size,
3863 JsonVariant *signature_json,
3864 TPM2B_DIGEST **ret_policy_digest) {
3865
3866 TSS2_RC rc;
3867 int r;
3868
3869 assert(c);
3870 assert(session);
3871 assert(pcr_selection);
3872 assert(public);
3873 assert(fp && fp_size > 0);
3874
3875 log_debug("Adding PCR signature policy.");
3876
3877 _cleanup_(tpm2_handle_freep) Tpm2Handle *pubkey_handle = NULL;
3878 r = tpm2_load_external(c, NULL, public, NULL, &pubkey_handle);
3879 if (r < 0)
3880 return r;
3881
3882 /* Acquire the "name" of what we just loaded */
3883 _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
3884 r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
3885 if (r < 0)
3886 return r;
3887
3888 /* If we have a signature, proceed with verifying the PCR digest */
3889 const TPMT_TK_VERIFIED *check_ticket;
3890 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
3891 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
3892 if (signature_json) {
3893 r = tpm2_policy_pcr(
3894 c,
3895 session,
3896 pcr_selection,
3897 &approved_policy);
3898 if (r < 0)
3899 return r;
3900
3901 _cleanup_free_ void *signature_raw = NULL;
3902 size_t signature_size;
3903
3904 r = find_signature(
3905 signature_json,
3906 pcr_selection,
3907 fp, fp_size,
3908 approved_policy->buffer,
3909 approved_policy->size,
3910 &signature_raw,
3911 &signature_size);
3912 if (r < 0)
3913 return r;
3914
3915 /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
3916 * hence we need to do the SHA256 part ourselves, first */
3917 TPM2B_DIGEST signature_hash = *approved_policy;
3918 r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
3919 if (r < 0)
3920 return r;
3921
3922 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size);
3923 if (r < 0)
3924 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
3925
3926 TPMT_SIGNATURE policy_signature = {
3927 .sigAlg = TPM2_ALG_RSASSA,
3928 .signature.rsassa = {
3929 .hash = TPM2_ALG_SHA256,
3930 .sig = TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw, signature_size),
3931 },
3932 };
3933
3934 rc = sym_Esys_VerifySignature(
3935 c->esys_context,
3936 pubkey_handle->esys_handle,
3937 ESYS_TR_NONE,
3938 ESYS_TR_NONE,
3939 ESYS_TR_NONE,
3940 &signature_hash,
3941 &policy_signature,
3942 &check_ticket_buffer);
3943 if (rc != TSS2_RC_SUCCESS)
3944 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3945 "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
3946
3947 check_ticket = check_ticket_buffer;
3948 } else {
3949 /* When enrolling, we pass a NULL ticket */
3950 static const TPMT_TK_VERIFIED check_ticket_null = {
3951 .tag = TPM2_ST_VERIFIED,
3952 .hierarchy = TPM2_RH_OWNER,
3953 };
3954
3955 check_ticket = &check_ticket_null;
3956 }
3957
3958 rc = sym_Esys_PolicyAuthorize(
3959 c->esys_context,
3960 session->esys_handle,
3961 ESYS_TR_NONE,
3962 ESYS_TR_NONE,
3963 ESYS_TR_NONE,
3964 approved_policy,
3965 /* policyRef= */ &(const TPM2B_NONCE) {},
3966 pubkey_name,
3967 check_ticket);
3968 if (rc != TSS2_RC_SUCCESS)
3969 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
3970 "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
3971
3972 return tpm2_get_policy_digest(c, session, ret_policy_digest);
3973 }
3974
3975 /* Extend 'digest' with the calculated policy hash. */
3976 int tpm2_calculate_sealing_policy(
3977 const Tpm2PCRValue *pcr_values,
3978 size_t n_pcr_values,
3979 const TPM2B_PUBLIC *public,
3980 bool use_pin,
3981 const Tpm2PCRLockPolicy *pcrlock_policy,
3982 TPM2B_DIGEST *digest) {
3983
3984 int r;
3985
3986 assert(pcr_values || n_pcr_values == 0);
3987 assert(digest);
3988
3989 if (public && pcrlock_policy)
3990 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Policies with both signed PCR and pcrlock are currently not supported.");
3991
3992 if (public) {
3993 r = tpm2_calculate_policy_authorize(public, NULL, digest);
3994 if (r < 0)
3995 return r;
3996 }
3997
3998 if (pcrlock_policy) {
3999 TPM2B_NV_PUBLIC nv_public;
4000
4001 r = tpm2_unmarshal_nv_public(
4002 pcrlock_policy->nv_public.iov_base,
4003 pcrlock_policy->nv_public.iov_len,
4004 &nv_public);
4005 if (r < 0)
4006 return r;
4007
4008 r = tpm2_calculate_policy_authorize_nv(&nv_public, digest);
4009 if (r < 0)
4010 return r;
4011 }
4012
4013 if (n_pcr_values > 0) {
4014 r = tpm2_calculate_policy_pcr(pcr_values, n_pcr_values, digest);
4015 if (r < 0)
4016 return r;
4017 }
4018
4019 if (use_pin) {
4020 r = tpm2_calculate_policy_auth_value(digest);
4021 if (r < 0)
4022 return r;
4023 }
4024
4025 return 0;
4026 }
4027
4028 static int tpm2_build_sealing_policy(
4029 Tpm2Context *c,
4030 const Tpm2Handle *session,
4031 uint32_t hash_pcr_mask,
4032 uint16_t pcr_bank,
4033 const TPM2B_PUBLIC *public,
4034 const void *fp,
4035 size_t fp_size,
4036 uint32_t pubkey_pcr_mask,
4037 JsonVariant *signature_json,
4038 bool use_pin,
4039 const Tpm2PCRLockPolicy *pcrlock_policy,
4040 TPM2B_DIGEST **ret_policy_digest) {
4041
4042 int r;
4043
4044 assert(c);
4045 assert(session);
4046 assert(pubkey_pcr_mask == 0 || public);
4047
4048 log_debug("Building sealing policy.");
4049
4050 if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
4051 r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);
4052 if (r < 0)
4053 return r;
4054 if (r == 0)
4055 log_debug("Selected TPM2 PCRs are not initialized on this system.");
4056 }
4057
4058 if (pubkey_pcr_mask != 0 && pcrlock_policy)
4059 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Policies with both signed PCR and pcrlock are currently not supported.");
4060
4061 if (pubkey_pcr_mask != 0) {
4062 TPML_PCR_SELECTION pcr_selection;
4063 tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
4064 r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
4065 if (r < 0)
4066 return r;
4067 }
4068
4069 if (pcrlock_policy) {
4070 _cleanup_(tpm2_handle_freep) Tpm2Handle *nv_handle = NULL;
4071
4072 r = tpm2_policy_super_pcr(
4073 c,
4074 session,
4075 &pcrlock_policy->prediction,
4076 pcrlock_policy->algorithm);
4077 if (r < 0)
4078 return r;
4079
4080 r = tpm2_deserialize(
4081 c,
4082 pcrlock_policy->nv_handle.iov_base,
4083 pcrlock_policy->nv_handle.iov_len,
4084 &nv_handle);
4085 if (r < 0)
4086 return r;
4087
4088 r = tpm2_policy_authorize_nv(
4089 c,
4090 session,
4091 nv_handle,
4092 NULL);
4093 if (r < 0)
4094 return r;
4095 }
4096
4097 if (hash_pcr_mask != 0) {
4098 TPML_PCR_SELECTION pcr_selection;
4099 tpm2_tpml_pcr_selection_from_mask(hash_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
4100 r = tpm2_policy_pcr(c, session, &pcr_selection, NULL);
4101 if (r < 0)
4102 return r;
4103 }
4104
4105 if (use_pin) {
4106 r = tpm2_policy_auth_value(c, session, NULL);
4107 if (r < 0)
4108 return r;
4109 }
4110
4111 r = tpm2_get_policy_digest(c, session, ret_policy_digest);
4112 if (r < 0)
4113 return r;
4114
4115 return 0;
4116 }
4117
4118 #if HAVE_OPENSSL
4119 static const struct {
4120 TPM2_ECC_CURVE tpm2_ecc_curve_id;
4121 int openssl_ecc_curve_id;
4122 } tpm2_openssl_ecc_curve_table[] = {
4123 { TPM2_ECC_NIST_P192, NID_X9_62_prime192v1, },
4124 { TPM2_ECC_NIST_P224, NID_secp224r1, },
4125 { TPM2_ECC_NIST_P256, NID_X9_62_prime256v1, },
4126 { TPM2_ECC_NIST_P384, NID_secp384r1, },
4127 { TPM2_ECC_NIST_P521, NID_secp521r1, },
4128 { TPM2_ECC_SM2_P256, NID_sm2, },
4129 };
4130
4131 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id, TPM2_ECC_CURVE *ret) {
4132 assert(ret);
4133
4134 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
4135 if (t->openssl_ecc_curve_id == openssl_ecc_curve_id) {
4136 *ret = t->tpm2_ecc_curve_id;
4137 return 0;
4138 }
4139
4140 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4141 "OpenSSL ECC curve id %d not supported.", openssl_ecc_curve_id);
4142 }
4143
4144 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id, int *ret) {
4145 assert(ret);
4146
4147 FOREACH_ARRAY(t, tpm2_openssl_ecc_curve_table, ELEMENTSOF(tpm2_openssl_ecc_curve_table))
4148 if (t->tpm2_ecc_curve_id == tpm2_ecc_curve_id) {
4149 *ret = t->openssl_ecc_curve_id;
4150 return 0;
4151 }
4152
4153 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4154 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id);
4155 }
4156
4157 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
4158
4159 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret) {
4160 int r;
4161
4162 assert(public);
4163 assert(ret);
4164
4165 const TPMT_PUBLIC *p = &public->publicArea;
4166 switch (p->type) {
4167 case TPM2_ALG_ECC: {
4168 int curve_id;
4169 r = tpm2_ecc_curve_to_openssl_curve_id(p->parameters.eccDetail.curveID, &curve_id);
4170 if (r < 0)
4171 return r;
4172
4173 const TPMS_ECC_POINT *point = &p->unique.ecc;
4174 return ecc_pkey_from_curve_x_y(
4175 curve_id,
4176 point->x.buffer,
4177 point->x.size,
4178 point->y.buffer,
4179 point->y.size,
4180 ret);
4181 }
4182 case TPM2_ALG_RSA: {
4183 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4184 * zero indicates that the exponent is the default of 2^16 + 1". */
4185 uint32_t exponent = htobe32(p->parameters.rsaDetail.exponent ?: TPM2_RSA_DEFAULT_EXPONENT);
4186 return rsa_pkey_from_n_e(
4187 p->unique.rsa.buffer,
4188 p->unique.rsa.size,
4189 &exponent,
4190 sizeof(exponent),
4191 ret);
4192 }
4193 default:
4194 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4195 "TPM2 asymmetric algorithm 0x%" PRIx16 " not supported.", p->type);
4196 }
4197 }
4198
4199 /* Be careful before changing anything in this function, as the TPM key "name" is calculated using the entire
4200 * TPMT_PUBLIC (after marshalling), and that "name" is used (for example) to calculate the policy hash for
4201 * the Authorize policy. So we must ensure this conversion of a PEM to TPM2B_PUBLIC does not change the
4202 * "name", because it would break unsealing of previously-sealed objects that used (for example)
4203 * tpm2_calculate_policy_authorize(). See bug #30546. */
4204 int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) {
4205 int key_id, r;
4206
4207 assert(pkey);
4208 assert(ret);
4209
4210 TPMT_PUBLIC public = {
4211 .nameAlg = TPM2_ALG_SHA256,
4212 .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH,
4213 .parameters.asymDetail = {
4214 .symmetric.algorithm = TPM2_ALG_NULL,
4215 .scheme.scheme = TPM2_ALG_NULL,
4216 },
4217 };
4218
4219 #if OPENSSL_VERSION_MAJOR >= 3
4220 key_id = EVP_PKEY_get_id(pkey);
4221 #else
4222 key_id = EVP_PKEY_id(pkey);
4223 #endif
4224
4225 switch (key_id) {
4226 case EVP_PKEY_EC: {
4227 public.type = TPM2_ALG_ECC;
4228
4229 int curve_id;
4230 _cleanup_free_ void *x = NULL, *y = NULL;
4231 size_t x_size, y_size;
4232 r = ecc_pkey_to_curve_x_y(pkey, &curve_id, &x, &x_size, &y, &y_size);
4233 if (r < 0)
4234 return log_debug_errno(r, "Could not get ECC key curve/x/y: %m");
4235
4236 TPM2_ECC_CURVE curve;
4237 r = tpm2_ecc_curve_from_openssl_curve_id(curve_id, &curve);
4238 if (r < 0)
4239 return r;
4240
4241 public.parameters.eccDetail.curveID = curve;
4242
4243 public.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
4244
4245 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
4246 if (r < 0)
4247 return log_debug_errno(r, "ECC key x size %zu too large.", x_size);
4248
4249 public.unique.ecc.x = TPM2B_ECC_PARAMETER_MAKE(x, x_size);
4250
4251 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
4252 if (r < 0)
4253 return log_debug_errno(r, "ECC key y size %zu too large.", y_size);
4254
4255 public.unique.ecc.y = TPM2B_ECC_PARAMETER_MAKE(y, y_size);
4256
4257 break;
4258 }
4259 case EVP_PKEY_RSA: {
4260 public.type = TPM2_ALG_RSA;
4261
4262 _cleanup_free_ void *n = NULL, *e = NULL;
4263 size_t n_size, e_size;
4264 r = rsa_pkey_to_n_e(pkey, &n, &n_size, &e, &e_size);
4265 if (r < 0)
4266 return log_debug_errno(r, "Could not get RSA key n/e: %m");
4267
4268 r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size);
4269 if (r < 0)
4270 return log_debug_errno(r, "RSA key n size %zu too large.", n_size);
4271
4272 public.unique.rsa = TPM2B_PUBLIC_KEY_RSA_MAKE(n, n_size);
4273 public.parameters.rsaDetail.keyBits = n_size * 8;
4274
4275 if (sizeof(uint32_t) < e_size)
4276 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
4277 "RSA key e size %zu too large.", e_size);
4278
4279 uint32_t exponent = 0;
4280 memcpy(&exponent, e, e_size);
4281 exponent = be32toh(exponent) >> (32 - e_size * 8);
4282
4283 /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of
4284 * zero indicates that the exponent is the default of 2^16 + 1". However, we have no reason
4285 * to special case it in our PEM->TPM2B_PUBLIC conversion, and doing so could break backwards
4286 * compatibility, so even if it is the "default" value of 0x10001, we do not set it to 0. */
4287 public.parameters.rsaDetail.exponent = exponent;
4288
4289 break;
4290 }
4291 default:
4292 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4293 "EVP_PKEY type %d not supported.", key_id);
4294 }
4295
4296 *ret = (TPM2B_PUBLIC) {
4297 .size = sizeof(public),
4298 .publicArea = public,
4299 };
4300
4301 return 0;
4302 }
4303 #endif
4304
4305 int tpm2_tpm2b_public_to_fingerprint(
4306 const TPM2B_PUBLIC *public,
4307 void **ret_fingerprint,
4308 size_t *ret_fingerprint_size) {
4309
4310 #if HAVE_OPENSSL
4311 int r;
4312
4313 assert(public);
4314 assert(ret_fingerprint);
4315 assert(ret_fingerprint_size);
4316
4317 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4318 r = tpm2_tpm2b_public_to_openssl_pkey(public, &pkey);
4319 if (r < 0)
4320 return r;
4321
4322 /* Hardcode fingerprint to SHA256 */
4323 return pubkey_fingerprint(pkey, EVP_sha256(), ret_fingerprint, ret_fingerprint_size);
4324 #else
4325 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
4326 #endif
4327 }
4328
4329 int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) {
4330 #if HAVE_OPENSSL
4331 int r;
4332
4333 assert(pem);
4334 assert(ret);
4335
4336 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4337 r = openssl_pkey_from_pem(pem, pem_size, &pkey);
4338 if (r < 0)
4339 return r;
4340
4341 return tpm2_tpm2b_public_from_openssl_pkey(pkey, ret);
4342 #else
4343 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
4344 #endif
4345 }
4346
4347 /* Marshal the public, private, and seed objects into a single nonstandard 'blob'. The public and private
4348 * objects are required, while the seed is optional. This is not a (publicly) standard format, this is
4349 * specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
4350 * tpm2_unmarshal_blob(). */
4351 int tpm2_marshal_blob(
4352 const TPM2B_PUBLIC *public,
4353 const TPM2B_PRIVATE *private,
4354 const TPM2B_ENCRYPTED_SECRET *seed,
4355 void **ret_blob,
4356 size_t *ret_blob_size) {
4357
4358 TSS2_RC rc;
4359
4360 assert(public);
4361 assert(private);
4362 assert(ret_blob);
4363 assert(ret_blob_size);
4364
4365 size_t max_size = sizeof(*private) + sizeof(*public);
4366 if (seed)
4367 max_size += sizeof(*seed);
4368
4369 _cleanup_free_ void *blob = malloc(max_size);
4370 if (!blob)
4371 return log_oom_debug();
4372
4373 size_t blob_size = 0;
4374 rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
4375 if (rc != TSS2_RC_SUCCESS)
4376 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4377 "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
4378
4379 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
4380 if (rc != TSS2_RC_SUCCESS)
4381 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4382 "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
4383
4384 if (seed) {
4385 rc = sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal(seed, blob, max_size, &blob_size);
4386 if (rc != TSS2_RC_SUCCESS)
4387 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4388 "Failed to marshal encrypted seed: %s", sym_Tss2_RC_Decode(rc));
4389 }
4390
4391 *ret_blob = TAKE_PTR(blob);
4392 *ret_blob_size = blob_size;
4393
4394 return 0;
4395 }
4396
4397 /* Unmarshal the 'blob' into public, private, and seed objects. The public and private objects are required
4398 * in the 'blob', while the seed is optional. This is not a (publicly) standard format, this is specific to
4399 * how we currently store the sealed object. This expects the 'blob' to have been created by
4400 * tpm2_marshal_blob(). */
4401 int tpm2_unmarshal_blob(
4402 const void *blob,
4403 size_t blob_size,
4404 TPM2B_PUBLIC *ret_public,
4405 TPM2B_PRIVATE *ret_private,
4406 TPM2B_ENCRYPTED_SECRET *ret_seed) {
4407
4408 TSS2_RC rc;
4409
4410 assert(blob);
4411 assert(ret_public);
4412 assert(ret_private);
4413 assert(ret_seed);
4414
4415 TPM2B_PRIVATE private = {};
4416 size_t offset = 0;
4417 rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
4418 if (rc != TSS2_RC_SUCCESS)
4419 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4420 "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
4421
4422 TPM2B_PUBLIC public = {};
4423 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
4424 if (rc != TSS2_RC_SUCCESS)
4425 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4426 "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
4427
4428 TPM2B_ENCRYPTED_SECRET seed = {};
4429 if (blob_size > offset) {
4430 rc = sym_Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal(blob, blob_size, &offset, &seed);
4431 if (rc != TSS2_RC_SUCCESS)
4432 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4433 "Failed to unmarshal encrypted seed: %s", sym_Tss2_RC_Decode(rc));
4434 }
4435
4436 *ret_public = public;
4437 *ret_private = private;
4438 *ret_seed = seed;
4439
4440 return 0;
4441 }
4442
4443 /* Calculate a serialized handle. Once the upstream tpm2-tss library provides an api to do this, we can
4444 * remove this function. The addition of this functionality in tpm2-tss may be tracked here:
4445 * https://github.com/tpm2-software/tpm2-tss/issues/2575 */
4446 int tpm2_calculate_serialize(
4447 TPM2_HANDLE handle,
4448 const TPM2B_NAME *name,
4449 const TPM2B_PUBLIC *public,
4450 void **ret_serialized,
4451 size_t *ret_serialized_size) {
4452
4453 TSS2_RC rc;
4454
4455 assert(name);
4456 assert(public);
4457 assert(ret_serialized);
4458 assert(ret_serialized_size);
4459
4460 size_t max_size = sizeof(TPM2_HANDLE) + sizeof(TPM2B_NAME) + sizeof(uint32_t) + sizeof(TPM2B_PUBLIC);
4461 _cleanup_free_ void *serialized = malloc(max_size);
4462 if (!serialized)
4463 return log_oom_debug();
4464
4465 size_t serialized_size = 0;
4466 rc = sym_Tss2_MU_TPM2_HANDLE_Marshal(handle, serialized, max_size, &serialized_size);
4467 if (rc != TSS2_RC_SUCCESS)
4468 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4469 "Failed to marshal tpm handle: %s", sym_Tss2_RC_Decode(rc));
4470
4471 rc = sym_Tss2_MU_TPM2B_NAME_Marshal(name, serialized, max_size, &serialized_size);
4472 if (rc != TSS2_RC_SUCCESS)
4473 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4474 "Failed to marshal name: %s", sym_Tss2_RC_Decode(rc));
4475
4476 /* This is defined (non-publicly) in the tpm2-tss source as IESYSC_KEY_RSRC, to a value of "1". */
4477 rc = sym_Tss2_MU_UINT32_Marshal(UINT32_C(1), serialized, max_size, &serialized_size);
4478 if (rc != TSS2_RC_SUCCESS)
4479 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4480 "Failed to marshal esys resource id: %s", sym_Tss2_RC_Decode(rc));
4481
4482 rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, serialized, max_size, &serialized_size);
4483 if (rc != TSS2_RC_SUCCESS)
4484 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4485 "Failed to marshal public: %s", sym_Tss2_RC_Decode(rc));
4486
4487 *ret_serialized = TAKE_PTR(serialized);
4488 *ret_serialized_size = serialized_size;
4489
4490 return 0;
4491 }
4492
4493 /* Serialize a handle. This produces a binary object that can be later deserialized (by the same TPM), even
4494 * across restarts of the TPM or reboots (assuming the handle is persistent). */
4495 int tpm2_serialize(
4496 Tpm2Context *c,
4497 const Tpm2Handle *handle,
4498 void **ret_serialized,
4499 size_t *ret_serialized_size) {
4500
4501 TSS2_RC rc;
4502
4503 assert(c);
4504 assert(handle);
4505 assert(ret_serialized);
4506 assert(ret_serialized_size);
4507
4508 _cleanup_(Esys_Freep) unsigned char *serialized = NULL;
4509 size_t size = 0;
4510 rc = sym_Esys_TR_Serialize(c->esys_context, handle->esys_handle, &serialized, &size);
4511 if (rc != TSS2_RC_SUCCESS)
4512 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4513 "Failed to serialize: %s", sym_Tss2_RC_Decode(rc));
4514
4515 *ret_serialized = TAKE_PTR(serialized);
4516 *ret_serialized_size = size;
4517
4518 return 0;
4519 }
4520
4521 int tpm2_deserialize(
4522 Tpm2Context *c,
4523 const void *serialized,
4524 size_t serialized_size,
4525 Tpm2Handle **ret_handle) {
4526
4527 TSS2_RC rc;
4528 int r;
4529
4530 assert(c);
4531 assert(serialized);
4532 assert(ret_handle);
4533
4534 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
4535 r = tpm2_handle_new(c, &handle);
4536 if (r < 0)
4537 return r;
4538
4539 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
4540 handle->flush = false;
4541
4542 rc = sym_Esys_TR_Deserialize(c->esys_context, serialized, serialized_size, &handle->esys_handle);
4543 if (rc != TSS2_RC_SUCCESS)
4544 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4545 "Failed to deserialize: %s", sym_Tss2_RC_Decode(rc));
4546
4547 *ret_handle = TAKE_PTR(handle);
4548
4549 return 0;
4550 }
4551
4552 #if HAVE_OPENSSL
4553
4554 /* KDFa() as defined by the TPM spec. */
4555 static int tpm2_kdfa(
4556 TPMI_ALG_HASH hash_alg,
4557 const void *key,
4558 size_t key_len,
4559 const char *label,
4560 const void *context,
4561 size_t context_len,
4562 size_t bits,
4563 void **ret_key,
4564 size_t *ret_key_len) {
4565
4566 int r;
4567
4568 assert(key);
4569 assert(label);
4570 assert(context || context_len == 0);
4571 assert(bits > 0);
4572 assert(bits <= SIZE_MAX - 7);
4573 assert(ret_key);
4574 assert(ret_key_len);
4575
4576 log_debug("Calculating KDFa().");
4577
4578 size_t len = DIV_ROUND_UP(bits, 8);
4579
4580 const char *hash_alg_name = tpm2_hash_alg_to_string(hash_alg);
4581 if (!hash_alg_name)
4582 return -EOPNOTSUPP;
4583
4584 _cleanup_free_ void *buf = NULL;
4585 r = kdf_kb_hmac_derive(
4586 "COUNTER",
4587 hash_alg_name,
4588 key,
4589 key_len,
4590 label,
4591 strlen(label),
4592 context,
4593 context_len,
4594 /* seed= */ NULL,
4595 /* seed_len= */ 0,
4596 len,
4597 &buf);
4598 if (r < 0)
4599 return r;
4600
4601 /* If the number of bits results in a partial byte, the TPM spec requires we zero the unrequested
4602 * bits in the MSB (i.e. at index 0). From the spec Part 1 ("Architecture") section on Key
4603 * Derivation Function, specifically KDFa():
4604 *
4605 * "The implied return from this function is a sequence of octets with a length equal to (bits + 7) /
4606 * 8. If bits is not an even multiple of 8, then the returned value occupies the least significant
4607 * bits of the returned octet array, and the additional, high-order bits in the 0th octet are
4608 * CLEAR. The unused bits of the most significant octet (MSO) are masked off and not shifted." */
4609 size_t partial = bits % 8;
4610 if (partial > 0)
4611 ((uint8_t*) buf)[0] &= 0xffu >> (8 - partial);
4612
4613 *ret_key = TAKE_PTR(buf);
4614 *ret_key_len = len;
4615
4616 return 0;
4617 }
4618
4619 /* KDFe() as defined by the TPM spec. */
4620 static int tpm2_kdfe(
4621 TPMI_ALG_HASH hash_alg,
4622 const void *shared_secret,
4623 size_t shared_secret_len,
4624 const char *label,
4625 const void *context_u,
4626 size_t context_u_size,
4627 const void *context_v,
4628 size_t context_v_size,
4629 size_t bits,
4630 void **ret_key,
4631 size_t *ret_key_len) {
4632
4633 int r;
4634
4635 assert(shared_secret);
4636 assert(label);
4637 assert(context_u);
4638 assert(context_v);
4639 assert(bits > 0);
4640 assert(bits <= SIZE_MAX - 7);
4641 assert(ret_key);
4642 assert(ret_key_len);
4643
4644 log_debug("Calculating KDFe().");
4645
4646 size_t len = DIV_ROUND_UP(bits, 8);
4647
4648 const char *hash_alg_name = tpm2_hash_alg_to_string(hash_alg);
4649 if (!hash_alg_name)
4650 return -EOPNOTSUPP;
4651
4652 size_t info_len = strlen(label) + 1 + context_u_size + context_v_size;
4653 _cleanup_free_ void *info = malloc(info_len);
4654 if (!info)
4655 return log_oom_debug();
4656
4657 void *end = mempcpy(mempcpy(stpcpy(info, label) + 1, context_u, context_u_size), context_v, context_v_size);
4658 /* assert we copied exactly the right amount that we allocated */
4659 assert(end > info && (uintptr_t) end - (uintptr_t) info == info_len);
4660
4661 _cleanup_free_ void *buf = NULL;
4662 r = kdf_ss_derive(
4663 hash_alg_name,
4664 shared_secret,
4665 shared_secret_len,
4666 /* salt= */ NULL,
4667 /* salt_size= */ 0,
4668 info,
4669 info_len,
4670 len,
4671 &buf);
4672 if (r < 0)
4673 return r;
4674
4675 *ret_key = TAKE_PTR(buf);
4676 *ret_key_len = len;
4677
4678 return 0;
4679 }
4680
4681 static int tpm2_calculate_seal_public(
4682 const TPM2B_PUBLIC *parent,
4683 const TPMA_OBJECT *attributes,
4684 const TPM2B_DIGEST *policy,
4685 const TPM2B_DIGEST *seed,
4686 const void *secret,
4687 size_t secret_size,
4688 TPM2B_PUBLIC *ret) {
4689
4690 int r;
4691
4692 assert(parent);
4693 assert(seed);
4694 assert(secret);
4695 assert(ret);
4696
4697 log_debug("Calculating public part of sealed object.");
4698
4699 struct iovec data[] = {
4700 IOVEC_MAKE((void*) seed->buffer, seed->size),
4701 IOVEC_MAKE((void*) secret, secret_size),
4702 };
4703 TPM2B_DIGEST unique;
4704 r = tpm2_digest_many(
4705 parent->publicArea.nameAlg,
4706 &unique,
4707 data,
4708 ELEMENTSOF(data),
4709 /* extend= */ false);
4710 if (r < 0)
4711 return r;
4712
4713 *ret = (TPM2B_PUBLIC) {
4714 .size = sizeof(TPMT_PUBLIC),
4715 .publicArea = {
4716 .type = TPM2_ALG_KEYEDHASH,
4717 .nameAlg = parent->publicArea.nameAlg,
4718 .objectAttributes = attributes ? *attributes : 0,
4719 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, unique.size),
4720 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
4721 .unique.keyedHash = unique,
4722 },
4723 };
4724
4725 return 0;
4726 }
4727
4728 static int tpm2_calculate_seal_private(
4729 const TPM2B_PUBLIC *parent,
4730 const TPM2B_NAME *name,
4731 const char *pin,
4732 const TPM2B_DIGEST *seed,
4733 const void *secret,
4734 size_t secret_size,
4735 TPM2B_PRIVATE *ret) {
4736
4737 TSS2_RC rc;
4738 int r;
4739
4740 assert(parent);
4741 assert(name);
4742 assert(seed);
4743 assert(secret);
4744 assert(ret);
4745
4746 log_debug("Calculating private part of sealed object.");
4747
4748 _cleanup_free_ void *storage_key = NULL;
4749 size_t storage_key_size;
4750 r = tpm2_kdfa(parent->publicArea.nameAlg,
4751 seed->buffer,
4752 seed->size,
4753 "STORAGE",
4754 name->name,
4755 name->size,
4756 (size_t) parent->publicArea.parameters.asymDetail.symmetric.keyBits.sym,
4757 &storage_key,
4758 &storage_key_size);
4759 if (r < 0)
4760 return log_debug_errno(r, "Could not calculate storage key KDFa: %m");
4761
4762 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
4763 if (r < 0)
4764 return -EOPNOTSUPP;
4765
4766 size_t bits = (size_t) r * 8;
4767
4768 _cleanup_free_ void *integrity_key = NULL;
4769 size_t integrity_key_size;
4770 r = tpm2_kdfa(parent->publicArea.nameAlg,
4771 seed->buffer,
4772 seed->size,
4773 "INTEGRITY",
4774 /* context= */ NULL,
4775 /* n_context= */ 0,
4776 bits,
4777 &integrity_key,
4778 &integrity_key_size);
4779 if (r < 0)
4780 return log_debug_errno(r, "Could not calculate integrity key KDFa: %m");
4781
4782 TPM2B_AUTH auth = {};
4783 if (pin) {
4784 r = tpm2_get_pin_auth(parent->publicArea.nameAlg, pin, &auth);
4785 if (r < 0)
4786 return r;
4787 }
4788
4789 TPM2B_SENSITIVE sensitive = {
4790 .size = sizeof(TPMT_SENSITIVE),
4791 .sensitiveArea = {
4792 .sensitiveType = TPM2_ALG_KEYEDHASH,
4793 .authValue = auth,
4794 .seedValue = *seed,
4795 .sensitive.bits = TPM2B_SENSITIVE_DATA_MAKE(secret, secret_size),
4796 },
4797 };
4798
4799 _cleanup_free_ void *marshalled_sensitive = malloc(sizeof(sensitive));
4800 if (!marshalled_sensitive)
4801 return log_oom_debug();
4802
4803 size_t marshalled_sensitive_size = 0;
4804 rc = sym_Tss2_MU_TPM2B_SENSITIVE_Marshal(
4805 &sensitive,
4806 marshalled_sensitive,
4807 sizeof(sensitive),
4808 &marshalled_sensitive_size);
4809 if (rc != TSS2_RC_SUCCESS)
4810 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4811 "Failed to marshal sensitive: %s", sym_Tss2_RC_Decode(rc));
4812
4813 const char *sym_alg = tpm2_sym_alg_to_string(parent->publicArea.parameters.asymDetail.symmetric.algorithm);
4814 if (!sym_alg)
4815 return -EOPNOTSUPP;
4816
4817 const char *sym_mode = tpm2_sym_mode_to_string(parent->publicArea.parameters.asymDetail.symmetric.mode.sym);
4818 if (!sym_mode)
4819 return -EOPNOTSUPP;
4820
4821 _cleanup_free_ void *encrypted_sensitive = NULL;
4822 size_t encrypted_sensitive_size;
4823 r = openssl_cipher(
4824 sym_alg,
4825 parent->publicArea.parameters.asymDetail.symmetric.keyBits.sym,
4826 sym_mode,
4827 storage_key, storage_key_size,
4828 /* iv= */ NULL, /* n_iv= */ 0,
4829 marshalled_sensitive, marshalled_sensitive_size,
4830 &encrypted_sensitive, &encrypted_sensitive_size);
4831 if (r < 0)
4832 return r;
4833
4834 const char *hash_alg_name = tpm2_hash_alg_to_string(parent->publicArea.nameAlg);
4835 if (!hash_alg_name)
4836 return -EOPNOTSUPP;
4837
4838 _cleanup_free_ void *hmac_buffer = NULL;
4839 size_t hmac_size = 0;
4840 struct iovec hmac_data[] = {
4841 IOVEC_MAKE((void*) encrypted_sensitive, encrypted_sensitive_size),
4842 IOVEC_MAKE((void*) name->name, name->size),
4843 };
4844 r = openssl_hmac_many(
4845 hash_alg_name,
4846 integrity_key,
4847 integrity_key_size,
4848 hmac_data,
4849 ELEMENTSOF(hmac_data),
4850 &hmac_buffer,
4851 &hmac_size);
4852 if (r < 0)
4853 return r;
4854
4855 TPM2B_DIGEST outer_hmac = TPM2B_DIGEST_MAKE(hmac_buffer, hmac_size);
4856
4857 TPM2B_PRIVATE private = {};
4858 size_t private_size = 0;
4859 rc = sym_Tss2_MU_TPM2B_DIGEST_Marshal(
4860 &outer_hmac,
4861 private.buffer,
4862 sizeof(private.buffer),
4863 &private_size);
4864 if (rc != TSS2_RC_SUCCESS)
4865 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
4866 "Failed to marshal digest: %s", sym_Tss2_RC_Decode(rc));
4867 private.size = private_size;
4868
4869 assert(sizeof(private.buffer) - private.size >= encrypted_sensitive_size);
4870 memcpy_safe(&private.buffer[private.size], encrypted_sensitive, encrypted_sensitive_size);
4871 private.size += encrypted_sensitive_size;
4872
4873 *ret = private;
4874
4875 return 0;
4876 }
4877
4878 static int tpm2_calculate_seal_rsa_seed(
4879 const TPM2B_PUBLIC *parent,
4880 void **ret_seed,
4881 size_t *ret_seed_size,
4882 void **ret_encrypted_seed,
4883 size_t *ret_encrypted_seed_size) {
4884
4885 int r;
4886
4887 assert(parent);
4888 assert(ret_seed);
4889 assert(ret_seed_size);
4890 assert(ret_encrypted_seed);
4891 assert(ret_encrypted_seed_size);
4892
4893 log_debug("Calculating encrypted seed for RSA sealed object.");
4894
4895 _cleanup_(EVP_PKEY_freep) EVP_PKEY *parent_pkey = NULL;
4896 r = tpm2_tpm2b_public_to_openssl_pkey(parent, &parent_pkey);
4897 if (r < 0)
4898 return log_debug_errno(r, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4899
4900 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
4901 if (r < 0)
4902 return -EOPNOTSUPP;
4903
4904 size_t seed_size = (size_t) r;
4905
4906 _cleanup_free_ void *seed = malloc(seed_size);
4907 if (!seed)
4908 return log_oom_debug();
4909
4910 r = crypto_random_bytes(seed, seed_size);
4911 if (r < 0)
4912 return log_debug_errno(r, "Failed to generate random seed: %m");
4913
4914 const char *hash_alg_name = tpm2_hash_alg_to_string(parent->publicArea.nameAlg);
4915 if (!hash_alg_name)
4916 return -EOPNOTSUPP;
4917
4918 _cleanup_free_ void *encrypted_seed = NULL;
4919 size_t encrypted_seed_size;
4920 r = rsa_oaep_encrypt_bytes(
4921 parent_pkey,
4922 hash_alg_name,
4923 "DUPLICATE",
4924 seed,
4925 seed_size,
4926 &encrypted_seed,
4927 &encrypted_seed_size);
4928 if (r < 0)
4929 return log_debug_errno(r, "Could not RSA-OAEP encrypt random seed: %m");
4930
4931 *ret_seed = TAKE_PTR(seed);
4932 *ret_seed_size = seed_size;
4933 *ret_encrypted_seed = TAKE_PTR(encrypted_seed);
4934 *ret_encrypted_seed_size = encrypted_seed_size;
4935
4936 return 0;
4937 }
4938
4939 static int tpm2_calculate_seal_ecc_seed(
4940 const TPM2B_PUBLIC *parent,
4941 void **ret_seed,
4942 size_t *ret_seed_size,
4943 void **ret_encrypted_seed,
4944 size_t *ret_encrypted_seed_size) {
4945
4946 TSS2_RC rc;
4947 int r;
4948
4949 assert(parent);
4950 assert(ret_seed);
4951 assert(ret_seed_size);
4952 assert(ret_encrypted_seed);
4953 assert(ret_encrypted_seed_size);
4954
4955 log_debug("Calculating encrypted seed for ECC sealed object.");
4956
4957 _cleanup_(EVP_PKEY_freep) EVP_PKEY *parent_pkey = NULL;
4958 r = tpm2_tpm2b_public_to_openssl_pkey(parent, &parent_pkey);
4959 if (r < 0)
4960 return log_debug_errno(r, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4961
4962 int curve_id;
4963 r = ecc_pkey_to_curve_x_y(
4964 parent_pkey,
4965 &curve_id,
4966 /* ret_x= */ NULL, /* ret_x_size= */ 0,
4967 /* ret_y= */ NULL, /* ret_y_size= */ 0);
4968 if (r < 0)
4969 return r;
4970
4971 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
4972 r = ecc_pkey_new(curve_id, &pkey);
4973 if (r < 0)
4974 return r;
4975
4976 _cleanup_free_ void *shared_secret = NULL;
4977 size_t shared_secret_size;
4978 r = ecc_ecdh(pkey, parent_pkey, &shared_secret, &shared_secret_size);
4979 if (r < 0)
4980 return log_debug_errno(r, "Could not generate ECC shared secret: %m");
4981
4982 _cleanup_free_ void *x = NULL, *y = NULL;
4983 size_t x_size, y_size;
4984 r = ecc_pkey_to_curve_x_y(pkey, /* curve_id= */ NULL, &x, &x_size, &y, &y_size);
4985 if (r < 0)
4986 return log_debug_errno(r, "Could not get ECC get x/y: %m");
4987
4988 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size);
4989 if (r < 0)
4990 return log_debug_errno(r, "ECC point x size %zu is too large: %m", x_size);
4991
4992 r = TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size);
4993 if (r < 0)
4994 return log_debug_errno(r, "ECC point y size %zu is too large: %m", y_size);
4995
4996 TPMS_ECC_POINT point = {
4997 .x = TPM2B_ECC_PARAMETER_MAKE(x, x_size),
4998 .y = TPM2B_ECC_PARAMETER_MAKE(y, y_size),
4999 };
5000
5001 _cleanup_free_ void *encrypted_seed = malloc(sizeof(point));
5002 if (!encrypted_seed)
5003 return log_oom_debug();
5004
5005 size_t encrypted_seed_size = 0;
5006 rc = sym_Tss2_MU_TPMS_ECC_POINT_Marshal(&point, encrypted_seed, sizeof(point), &encrypted_seed_size);
5007 if (rc != TPM2_RC_SUCCESS)
5008 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5009 "Failed to marshal ECC point: %s", sym_Tss2_RC_Decode(rc));
5010
5011 r = tpm2_hash_alg_to_size(parent->publicArea.nameAlg);
5012 if (r < 0)
5013 return -EOPNOTSUPP;
5014
5015 size_t bits = (size_t) r * 8;
5016
5017 _cleanup_free_ void *seed = NULL;
5018 size_t seed_size = 0; /* Explicit initialization to appease gcc */
5019 r = tpm2_kdfe(parent->publicArea.nameAlg,
5020 shared_secret,
5021 shared_secret_size,
5022 "DUPLICATE",
5023 x,
5024 x_size,
5025 parent->publicArea.unique.ecc.x.buffer,
5026 parent->publicArea.unique.ecc.x.size,
5027 bits,
5028 &seed,
5029 &seed_size);
5030 if (r < 0)
5031 return log_debug_errno(r, "Could not calculate KDFe: %m");
5032
5033 *ret_seed = TAKE_PTR(seed);
5034 *ret_seed_size = seed_size;
5035 *ret_encrypted_seed = TAKE_PTR(encrypted_seed);
5036 *ret_encrypted_seed_size = encrypted_seed_size;
5037
5038 return 0;
5039 }
5040
5041 static int tpm2_calculate_seal_seed(
5042 const TPM2B_PUBLIC *parent,
5043 TPM2B_DIGEST *ret_seed,
5044 TPM2B_ENCRYPTED_SECRET *ret_encrypted_seed) {
5045
5046 int r;
5047
5048 assert(parent);
5049 assert(ret_seed);
5050 assert(ret_encrypted_seed);
5051
5052 log_debug("Calculating encrypted seed for sealed object.");
5053
5054 _cleanup_free_ void *seed = NULL, *encrypted_seed = NULL;
5055 size_t seed_size = 0, encrypted_seed_size = 0; /* Explicit initialization to appease gcc */
5056 if (parent->publicArea.type == TPM2_ALG_RSA)
5057 r = tpm2_calculate_seal_rsa_seed(parent, &seed, &seed_size, &encrypted_seed, &encrypted_seed_size);
5058 else if (parent->publicArea.type == TPM2_ALG_ECC)
5059 r = tpm2_calculate_seal_ecc_seed(parent, &seed, &seed_size, &encrypted_seed, &encrypted_seed_size);
5060 else
5061 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5062 "Unsupported parent key type 0x%" PRIx16, parent->publicArea.type);
5063 if (r < 0)
5064 return log_debug_errno(r, "Could not calculate encrypted seed: %m");
5065
5066 *ret_seed = TPM2B_DIGEST_MAKE(seed, seed_size);
5067 *ret_encrypted_seed = TPM2B_ENCRYPTED_SECRET_MAKE(encrypted_seed, encrypted_seed_size);
5068
5069 return 0;
5070 }
5071
5072 #endif /* HAVE_OPENSSL */
5073
5074 int tpm2_calculate_seal(
5075 TPM2_HANDLE parent_handle,
5076 const TPM2B_PUBLIC *parent_public,
5077 const TPMA_OBJECT *attributes,
5078 const struct iovec *secret,
5079 const TPM2B_DIGEST *policy,
5080 const char *pin,
5081 struct iovec *ret_secret,
5082 struct iovec *ret_blob,
5083 struct iovec *ret_serialized_parent) {
5084
5085 #if HAVE_OPENSSL
5086 int r;
5087
5088 assert(parent_public);
5089 assert(iovec_is_valid(secret));
5090 assert(secret || ret_secret);
5091 assert(!(secret && ret_secret)); /* Either provide a secret, or we create one, but not both */
5092 assert(ret_blob);
5093 assert(ret_serialized_parent);
5094
5095 log_debug("Calculating sealed object.");
5096
5097 /* Default to the SRK. */
5098 if (parent_handle == 0)
5099 parent_handle = TPM2_SRK_HANDLE;
5100
5101 switch (TPM2_HANDLE_TYPE(parent_handle)) {
5102 case TPM2_HT_PERSISTENT:
5103 case TPM2_HT_NV_INDEX:
5104 break;
5105 case TPM2_HT_TRANSIENT:
5106 log_warning("Handle is transient, sealed secret may not be recoverable.");
5107 break;
5108 default:
5109 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5110 "Handle 0x%" PRIx32 " not persistent, transient, or NV.",
5111 parent_handle);
5112 }
5113
5114 _cleanup_(iovec_done_erase) struct iovec generated_secret = {};
5115 if (!secret) {
5116 /* No secret provided, generate a random secret. We use SHA256 digest length, though it can
5117 * be up to TPM2_MAX_SEALED_DATA. The secret length is not limited to the nameAlg hash
5118 * size. */
5119 generated_secret.iov_len = TPM2_SHA256_DIGEST_SIZE;
5120 generated_secret.iov_base = malloc(generated_secret.iov_len);
5121 if (!generated_secret.iov_base)
5122 return log_oom_debug();
5123
5124 r = crypto_random_bytes(generated_secret.iov_base, generated_secret.iov_len);
5125 if (r < 0)
5126 return log_debug_errno(r, "Failed to generate secret key: %m");
5127
5128 secret = &generated_secret;
5129 }
5130
5131 if (secret->iov_len > TPM2_MAX_SEALED_DATA)
5132 return log_debug_errno(SYNTHETIC_ERRNO(EOVERFLOW),
5133 "Secret size %zu too large, limit is %d bytes.",
5134 secret->iov_len, TPM2_MAX_SEALED_DATA);
5135
5136 TPM2B_DIGEST random_seed;
5137 TPM2B_ENCRYPTED_SECRET seed;
5138 r = tpm2_calculate_seal_seed(parent_public, &random_seed, &seed);
5139 if (r < 0)
5140 return r;
5141
5142 TPM2B_PUBLIC public;
5143 r = tpm2_calculate_seal_public(parent_public, attributes, policy, &random_seed, secret->iov_base, secret->iov_len, &public);
5144 if (r < 0)
5145 return r;
5146
5147 TPM2B_NAME name;
5148 r = tpm2_calculate_pubkey_name(&public.publicArea, &name);
5149 if (r < 0)
5150 return r;
5151
5152 TPM2B_PRIVATE private;
5153 r = tpm2_calculate_seal_private(parent_public, &name, pin, &random_seed, secret->iov_base, secret->iov_len, &private);
5154 if (r < 0)
5155 return r;
5156
5157 _cleanup_(iovec_done) struct iovec blob = {};
5158 r = tpm2_marshal_blob(&public, &private, &seed, &blob.iov_base, &blob.iov_len);
5159 if (r < 0)
5160 return log_debug_errno(r, "Could not create sealed blob: %m");
5161
5162 TPM2B_NAME parent_name;
5163 r = tpm2_calculate_pubkey_name(&parent_public->publicArea, &parent_name);
5164 if (r < 0)
5165 return r;
5166
5167 _cleanup_(iovec_done) struct iovec serialized_parent = {};
5168 r = tpm2_calculate_serialize(
5169 parent_handle,
5170 &parent_name,
5171 parent_public,
5172 &serialized_parent.iov_base,
5173 &serialized_parent.iov_len);
5174 if (r < 0)
5175 return r;
5176
5177 if (ret_secret)
5178 *ret_secret = TAKE_STRUCT(generated_secret);
5179 *ret_blob = TAKE_STRUCT(blob);
5180 *ret_serialized_parent = TAKE_STRUCT(serialized_parent);
5181
5182 return 0;
5183 #else /* HAVE_OPENSSL */
5184 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
5185 #endif
5186 }
5187
5188 int tpm2_seal(Tpm2Context *c,
5189 uint32_t seal_key_handle,
5190 const TPM2B_DIGEST *policy,
5191 const char *pin,
5192 struct iovec *ret_secret,
5193 struct iovec *ret_blob,
5194 uint16_t *ret_primary_alg,
5195 struct iovec *ret_srk) {
5196
5197 uint16_t primary_alg = 0;
5198 int r;
5199
5200 assert(ret_secret);
5201 assert(ret_blob);
5202
5203 /* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
5204 * is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
5205 * generate a "primary" key pair derived from that (ECC if possible, RSA as fallback). Given the seed
5206 * remains fixed this will result in the same key pair whenever we specify the exact same parameters
5207 * for it. We then create a PCR-bound policy session, which calculates a hash on the current PCR
5208 * values of the indexes we specify. We then generate a randomized key on the host (which is the key
5209 * we actually enroll in the LUKS2 keyslots), which we upload into the TPM2, where it is encrypted
5210 * with the "primary" key, taking the PCR policy session into account. We then download the encrypted
5211 * key from the TPM2 ("sealing") and marshall it into binary form, which is ultimately placed in the
5212 * LUKS2 JSON header.
5213 *
5214 * The TPM2 "seed" key and "primary" keys never leave the TPM2 chip (and cannot be extracted at
5215 * all). The random key we enroll in LUKS2 we generate on the host using the Linux random device. It
5216 * is stored in the LUKS2 JSON only in encrypted form with the "primary" key of the TPM2 chip, thus
5217 * binding the unlocking to the TPM2 chip. */
5218
5219 usec_t start = now(CLOCK_MONOTONIC);
5220
5221 TPMA_OBJECT hmac_attributes =
5222 TPMA_OBJECT_FIXEDTPM |
5223 TPMA_OBJECT_FIXEDPARENT;
5224
5225 /* If protected by PIN, a user-selected low-entropy password, enable DA protection.
5226 Without a PIN, the key's left protected only by a PCR policy, which does not benefit
5227 from DA protection. */
5228 hmac_attributes |= pin ? 0 : TPMA_OBJECT_NODA;
5229
5230 /* We use a keyed hash object (i.e. HMAC) to store the secret key we want to use for unlocking the
5231 * LUKS2 volume with. We don't ever use for HMAC/keyed hash operations however, we just use it
5232 * because it's a key type that is universally supported and suitable for symmetric binary blobs. */
5233 TPMT_PUBLIC hmac_template = {
5234 .type = TPM2_ALG_KEYEDHASH,
5235 .nameAlg = TPM2_ALG_SHA256,
5236 .objectAttributes = hmac_attributes,
5237 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
5238 .unique.keyedHash.size = SHA256_DIGEST_SIZE,
5239 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
5240 };
5241
5242 TPMS_SENSITIVE_CREATE hmac_sensitive = {
5243 .data.size = hmac_template.unique.keyedHash.size,
5244 };
5245
5246 CLEANUP_ERASE(hmac_sensitive);
5247
5248 if (pin) {
5249 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &hmac_sensitive.userAuth);
5250 if (r < 0)
5251 return r;
5252 }
5253
5254 assert(sizeof(hmac_sensitive.data.buffer) >= hmac_sensitive.data.size);
5255
5256 (void) tpm2_credit_random(c);
5257
5258 log_debug("Generating secret key data.");
5259
5260 r = crypto_random_bytes(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
5261 if (r < 0)
5262 return log_debug_errno(r, "Failed to generate secret key: %m");
5263
5264 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
5265 if (ret_srk) {
5266 _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
5267
5268 if (IN_SET(seal_key_handle, 0, TPM2_SRK_HANDLE)) {
5269 r = tpm2_get_or_create_srk(
5270 c,
5271 /* session= */ NULL,
5272 &primary_public,
5273 /* ret_name= */ NULL,
5274 /* ret_qname= */ NULL,
5275 &primary_handle);
5276 if (r < 0)
5277 return r;
5278 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle), TPM2_HT_TRANSIENT, TPM2_HT_PERSISTENT)) {
5279 r = tpm2_index_to_handle(
5280 c,
5281 seal_key_handle,
5282 /* session= */ NULL,
5283 &primary_public,
5284 /* ret_name= */ NULL,
5285 /* ret_qname= */ NULL,
5286 &primary_handle);
5287 if (r < 0)
5288 return r;
5289 if (r == 0)
5290 /* We do NOT automatically create anything other than the SRK */
5291 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
5292 "No handle found at index 0x%" PRIx32, seal_key_handle);
5293 } else
5294 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5295 "Seal key handle 0x%" PRIx32 " is neither transient nor persistent.",
5296 seal_key_handle);
5297
5298 primary_alg = primary_public->publicArea.type;
5299 } else {
5300 if (seal_key_handle != 0)
5301 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
5302
5303 /* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
5304 primary_alg = TPM2_ALG_ECC;
5305
5306 TPM2B_PUBLIC template = {
5307 .size = sizeof(TPMT_PUBLIC),
5308 };
5309 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5310 if (r < 0)
5311 return log_debug_errno(r, "Could not get legacy ECC template: %m");
5312
5313 if (!tpm2_supports_tpmt_public(c, &template.publicArea)) {
5314 primary_alg = TPM2_ALG_RSA;
5315
5316 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5317 if (r < 0)
5318 return log_debug_errno(r, "Could not get legacy RSA template: %m");
5319
5320 if (!tpm2_supports_tpmt_public(c, &template.publicArea))
5321 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5322 "TPM does not support either ECC or RSA legacy template.");
5323 }
5324
5325 r = tpm2_create_primary(
5326 c,
5327 /* session= */ NULL,
5328 &template,
5329 /* sensitive= */ NULL,
5330 /* ret_public= */ NULL,
5331 &primary_handle);
5332 if (r < 0)
5333 return r;
5334 }
5335
5336 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
5337 r = tpm2_make_encryption_session(c, primary_handle, /* bind_key= */ NULL, &encryption_session);
5338 if (r < 0)
5339 return r;
5340
5341 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
5342 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
5343 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
5344 if (r < 0)
5345 return r;
5346
5347 _cleanup_(iovec_done_erase) struct iovec secret = {};
5348 secret.iov_base = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
5349 if (!secret.iov_base)
5350 return log_oom_debug();
5351 secret.iov_len = hmac_sensitive.data.size;
5352
5353 log_debug("Marshalling private and public part of HMAC key.");
5354
5355 _cleanup_(iovec_done) struct iovec blob = {};
5356 r = tpm2_marshal_blob(public, private, /* seed= */ NULL, &blob.iov_base, &blob.iov_len);
5357 if (r < 0)
5358 return log_debug_errno(r, "Could not create sealed blob: %m");
5359
5360 if (DEBUG_LOGGING)
5361 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5362
5363 if (ret_srk) {
5364 _cleanup_(iovec_done) struct iovec srk = {};
5365 _cleanup_(Esys_Freep) void *tmp = NULL;
5366 size_t tmp_size;
5367
5368 r = tpm2_serialize(c, primary_handle, &tmp, &tmp_size);
5369 if (r < 0)
5370 return r;
5371
5372 /*
5373 * make a copy since we don't want the caller to understand that
5374 * ESYS allocated the pointer. It would make tracking what deallocator
5375 * to use for srk in which context a PITA.
5376 */
5377 srk.iov_base = memdup(tmp, tmp_size);
5378 if (!srk.iov_base)
5379 return log_oom_debug();
5380 srk.iov_len = tmp_size;
5381
5382 *ret_srk = TAKE_STRUCT(srk);
5383 }
5384
5385 *ret_secret = TAKE_STRUCT(secret);
5386 *ret_blob = TAKE_STRUCT(blob);
5387
5388 if (ret_primary_alg)
5389 *ret_primary_alg = primary_alg;
5390
5391 return 0;
5392 }
5393
5394 #define RETRY_UNSEAL_MAX 30u
5395
5396 int tpm2_unseal(Tpm2Context *c,
5397 uint32_t hash_pcr_mask,
5398 uint16_t pcr_bank,
5399 const struct iovec *pubkey,
5400 uint32_t pubkey_pcr_mask,
5401 JsonVariant *signature,
5402 const char *pin,
5403 const Tpm2PCRLockPolicy *pcrlock_policy,
5404 uint16_t primary_alg,
5405 const struct iovec *blob,
5406 const struct iovec *known_policy_hash,
5407 const struct iovec *srk,
5408 struct iovec *ret_secret) {
5409
5410 TSS2_RC rc;
5411 int r;
5412
5413 assert(iovec_is_set(blob));
5414 assert(iovec_is_valid(known_policy_hash));
5415 assert(iovec_is_valid(pubkey));
5416 assert(ret_secret);
5417
5418 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
5419 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
5420
5421 /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
5422 * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy session.
5423 * Given we pass the same parameters, this will result in the same "primary" key, and same policy
5424 * hash (the latter of course, only if the PCR values didn't change in between). We unmarshal the
5425 * encrypted key we stored in the LUKS2 JSON token header and upload it into the TPM2, where it is
5426 * decrypted if the seed and the PCR policy were right ("unsealing"). We then download the result,
5427 * and use it to unlock the LUKS2 volume. */
5428
5429 usec_t start = now(CLOCK_MONOTONIC);
5430
5431 TPM2B_PUBLIC public;
5432 TPM2B_PRIVATE private;
5433 TPM2B_ENCRYPTED_SECRET seed = {};
5434 r = tpm2_unmarshal_blob(blob->iov_base, blob->iov_len, &public, &private, &seed);
5435 if (r < 0)
5436 return log_debug_errno(r, "Could not extract parts from blob: %m");
5437
5438 /* Older code did not save the pcr_bank, and unsealing needed to detect the best pcr bank to use,
5439 * so we need to handle that legacy situation. */
5440 if (pcr_bank == UINT16_MAX) {
5441 r = tpm2_get_best_pcr_bank(c, hash_pcr_mask|pubkey_pcr_mask, &pcr_bank);
5442 if (r < 0)
5443 return r;
5444 }
5445
5446 _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
5447 if (iovec_is_set(srk)) {
5448 r = tpm2_deserialize(c, srk->iov_base, srk->iov_len, &primary_handle);
5449 if (r < 0)
5450 return r;
5451 } else if (primary_alg != 0) {
5452 TPM2B_PUBLIC template = {
5453 .size = sizeof(TPMT_PUBLIC),
5454 };
5455 r = tpm2_get_legacy_template(primary_alg, &template.publicArea);
5456 if (r < 0)
5457 return log_debug_errno(r, "Could not get legacy template: %m");
5458
5459 r = tpm2_create_primary(
5460 c,
5461 /* session= */ NULL,
5462 &template,
5463 /* sensitive= */ NULL,
5464 /* ret_public= */ NULL,
5465 &primary_handle);
5466 if (r < 0)
5467 return r;
5468 } else
5469 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
5470 "No SRK or primary alg provided.");
5471
5472 if (seed.size > 0) {
5473 /* This is a calculated (or duplicated) sealed object, and must be imported. */
5474 _cleanup_free_ TPM2B_PRIVATE *imported_private = NULL;
5475 r = tpm2_import(c,
5476 primary_handle,
5477 /* session= */ NULL,
5478 &public,
5479 &private,
5480 &seed,
5481 /* encryption_key= */ NULL,
5482 /* symmetric= */ NULL,
5483 &imported_private);
5484 if (r < 0)
5485 return r;
5486
5487 private = *imported_private;
5488 }
5489
5490 log_debug("Loading HMAC key into TPM.");
5491
5492 /*
5493 * Nothing sensitive on the bus, no need for encryption. Even if an attacker
5494 * gives you back a different key, the session initiation will fail. In the
5495 * SRK model, the tpmKey is verified. In the non-srk model, with pin, the bindKey
5496 * provides protections.
5497 */
5498 _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
5499 r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
5500 if (r < 0)
5501 return r;
5502
5503 TPM2B_PUBLIC pubkey_tpm2b;
5504 _cleanup_(iovec_done) struct iovec fp = {};
5505 if (iovec_is_set(pubkey)) {
5506 r = tpm2_tpm2b_public_from_pem(pubkey->iov_base, pubkey->iov_len, &pubkey_tpm2b);
5507 if (r < 0)
5508 return log_debug_errno(r, "Could not create TPMT_PUBLIC: %m");
5509
5510 r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp.iov_base, &fp.iov_len);
5511 if (r < 0)
5512 return log_debug_errno(r, "Could not get key fingerprint: %m");
5513 }
5514
5515 /*
5516 * if a pin is set for the seal object, use it to bind the session
5517 * key to that object. This prevents active bus interposers from
5518 * faking a TPM and seeing the unsealed value. An active interposer
5519 * could fake a TPM, satisfying the encrypted session, and just
5520 * forward everything to the *real* TPM.
5521 */
5522 r = tpm2_set_auth(c, hmac_key, pin);
5523 if (r < 0)
5524 return r;
5525
5526 _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
5527 r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
5528 if (r < 0)
5529 return r;
5530
5531 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
5532 for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
5533 _cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
5534 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
5535 r = tpm2_make_policy_session(
5536 c,
5537 primary_handle,
5538 encryption_session,
5539 &policy_session);
5540 if (r < 0)
5541 return r;
5542
5543 r = tpm2_build_sealing_policy(
5544 c,
5545 policy_session,
5546 hash_pcr_mask,
5547 pcr_bank,
5548 iovec_is_set(pubkey) ? &pubkey_tpm2b : NULL,
5549 fp.iov_base, fp.iov_len,
5550 pubkey_pcr_mask,
5551 signature,
5552 !!pin,
5553 pcrlock_policy,
5554 &policy_digest);
5555 if (r < 0)
5556 return r;
5557
5558 /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
5559 * wait until the TPM2 tells us to go away. */
5560 if (iovec_is_set(known_policy_hash) && memcmp_nn(policy_digest->buffer,
5561 policy_digest->size,
5562 known_policy_hash->iov_base,
5563 known_policy_hash->iov_len) != 0) {
5564 #if HAVE_OPENSSL
5565 if (iovec_is_set(pubkey) &&
5566 pubkey_tpm2b.publicArea.type == TPM2_ALG_RSA &&
5567 pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent == TPM2_RSA_DEFAULT_EXPONENT) {
5568 /* Due to bug #30546, if using RSA pubkey with the default exponent, we may
5569 * need to set the exponent to the TPM special-case value of 0 and retry. */
5570 log_debug("Policy hash mismatch, retrying with RSA pubkey exponent set to 0.");
5571 pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent = 0;
5572 continue;
5573 } else
5574 #endif
5575 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
5576 "Current policy digest does not match stored policy digest, cancelling "
5577 "TPM2 authentication attempt.");
5578 }
5579
5580 log_debug("Unsealing HMAC key.");
5581
5582 rc = sym_Esys_Unseal(
5583 c->esys_context,
5584 hmac_key->esys_handle,
5585 policy_session->esys_handle,
5586 encryption_session->esys_handle, /* use HMAC session to enable parameter encryption */
5587 ESYS_TR_NONE,
5588 &unsealed);
5589 if (rc == TSS2_RC_SUCCESS)
5590 break;
5591 if (rc != TPM2_RC_PCR_CHANGED || i == 0)
5592 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5593 "Failed to unseal HMAC key in TPM: %s", sym_Tss2_RC_Decode(rc));
5594 log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
5595 }
5596
5597 _cleanup_(iovec_done_erase) struct iovec secret = {};
5598 secret.iov_base = memdup(unsealed->buffer, unsealed->size);
5599 explicit_bzero_safe(unsealed->buffer, unsealed->size);
5600 if (!secret.iov_base)
5601 return log_oom_debug();
5602 secret.iov_len = unsealed->size;
5603
5604 if (DEBUG_LOGGING)
5605 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
5606
5607 *ret_secret = TAKE_STRUCT(secret);
5608
5609 return 0;
5610 }
5611
5612 static TPM2_HANDLE generate_random_nv_index(void) {
5613 return TPM2_NV_INDEX_FIRST + (TPM2_HANDLE) random_u64_range(TPM2_NV_INDEX_LAST - TPM2_NV_INDEX_FIRST + 1);
5614 }
5615
5616 int tpm2_define_policy_nv_index(
5617 Tpm2Context *c,
5618 const Tpm2Handle *session,
5619 TPM2_HANDLE requested_nv_index,
5620 const TPM2B_DIGEST *write_policy,
5621 const char *pin,
5622 const TPM2B_AUTH *auth,
5623 TPM2_HANDLE *ret_nv_index,
5624 Tpm2Handle **ret_nv_handle,
5625 TPM2B_NV_PUBLIC *ret_nv_public) {
5626
5627 _cleanup_(tpm2_handle_freep) Tpm2Handle *new_handle = NULL;
5628 TSS2_RC rc;
5629 int r;
5630
5631 assert(c);
5632 assert(pin || auth);
5633
5634 r = tpm2_handle_new(c, &new_handle);
5635 if (r < 0)
5636 return r;
5637
5638 new_handle->flush = false; /* This is a persistent NV index, don't flush hence */
5639
5640 TPM2B_AUTH _auth = {};
5641 CLEANUP_ERASE(_auth);
5642
5643 if (!auth) {
5644 r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &_auth);
5645 if (r < 0)
5646 return r;
5647
5648 auth = &_auth;
5649 }
5650
5651 for (unsigned try = 0; try < 25U; try++) {
5652 TPM2_HANDLE nv_index;
5653
5654 if (requested_nv_index != 0)
5655 nv_index = requested_nv_index;
5656 else
5657 nv_index = generate_random_nv_index();
5658
5659 TPM2B_NV_PUBLIC public_info = {
5660 .size = sizeof_field(TPM2B_NV_PUBLIC, nvPublic),
5661 .nvPublic = {
5662 .nvIndex = nv_index,
5663 .nameAlg = TPM2_ALG_SHA256,
5664 .attributes = TPM2_NT_ORDINARY | TPMA_NV_WRITEALL | TPMA_NV_POLICYWRITE | TPMA_NV_OWNERREAD,
5665 .dataSize = offsetof(TPMT_HA, digest) + tpm2_hash_alg_to_size(TPM2_ALG_SHA256),
5666 },
5667 };
5668
5669 if (write_policy)
5670 public_info.nvPublic.authPolicy = *write_policy;
5671
5672 rc = sym_Esys_NV_DefineSpace(
5673 c->esys_context,
5674 /* authHandle= */ ESYS_TR_RH_OWNER,
5675 /* shandle1= */ session ? session->esys_handle : ESYS_TR_PASSWORD,
5676 /* shandle2= */ ESYS_TR_NONE,
5677 /* shandle3= */ ESYS_TR_NONE,
5678 auth,
5679 &public_info,
5680 &new_handle->esys_handle);
5681
5682 if (rc == TSS2_RC_SUCCESS) {
5683 log_debug("NV Index 0x%" PRIx32 " successfully allocated.", nv_index);
5684
5685 if (ret_nv_index)
5686 *ret_nv_index = nv_index;
5687
5688 if (ret_nv_handle)
5689 *ret_nv_handle = TAKE_PTR(new_handle);
5690
5691 if (ret_nv_public)
5692 *ret_nv_public = public_info;
5693
5694 return 0;
5695 }
5696 if (rc != TPM2_RC_NV_DEFINED)
5697 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5698 "Failed to allocate NV index: %s", sym_Tss2_RC_Decode(rc));
5699
5700 if (requested_nv_index != 0) {
5701 assert(nv_index == requested_nv_index);
5702 return log_debug_errno(SYNTHETIC_ERRNO(EEXIST),
5703 "Requested NV index 0x%" PRIx32 " already taken.", requested_nv_index);
5704 }
5705
5706 log_debug("NV index 0x%" PRIu32 " already taken, trying another one (%u tries left)", nv_index, try);
5707 }
5708
5709 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5710 "Too many attempts trying to allocate NV index: %s", sym_Tss2_RC_Decode(rc));
5711 }
5712
5713 int tpm2_write_policy_nv_index(
5714 Tpm2Context *c,
5715 const Tpm2Handle *policy_session,
5716 TPM2_HANDLE nv_index,
5717 const Tpm2Handle *nv_handle,
5718 const TPM2B_DIGEST *policy_digest) {
5719
5720 TSS2_RC rc;
5721
5722 assert(c);
5723 assert(policy_session);
5724 assert(nv_handle);
5725 assert(policy_digest);
5726
5727 if (policy_digest->size != tpm2_hash_alg_to_size(TPM2_ALG_SHA256))
5728 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Policy to store in NV index has wrong size.");
5729
5730 TPMT_HA ha = {
5731 .hashAlg = TPM2_ALG_SHA256,
5732 };
5733 assert(policy_digest->size <= sizeof_field(TPMT_HA, digest));
5734 memcpy_safe(&ha.digest, policy_digest->buffer, policy_digest->size);
5735
5736 TPM2B_MAX_NV_BUFFER buffer = {};
5737 size_t written = 0;
5738 rc = sym_Tss2_MU_TPMT_HA_Marshal(&ha, buffer.buffer, sizeof(buffer.buffer), &written);
5739 if (rc != TSS2_RC_SUCCESS)
5740 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5741 "Failed to marshal policy digest.");
5742
5743 buffer.size = written;
5744
5745 rc = sym_Esys_NV_Write(
5746 c->esys_context,
5747 /* authHandle= */ nv_handle->esys_handle,
5748 /* nvIndex= */ nv_handle->esys_handle,
5749 /* shandle1= */ policy_session->esys_handle,
5750 /* shandle2= */ ESYS_TR_NONE,
5751 /* shandle3= */ ESYS_TR_NONE,
5752 &buffer,
5753 /* offset= */ 0);
5754 if (rc != TSS2_RC_SUCCESS)
5755 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5756 "Failed to write NV index: %s", sym_Tss2_RC_Decode(rc));
5757
5758 if (DEBUG_LOGGING) {
5759 _cleanup_free_ char *h = NULL;
5760 h = hexmem(policy_digest->buffer, policy_digest->size);
5761 log_debug("Written policy digest %s to NV index 0x%x", strnull(h), nv_index);
5762 }
5763
5764 return 0;
5765 }
5766
5767 int tpm2_undefine_policy_nv_index(
5768 Tpm2Context *c,
5769 const Tpm2Handle *session,
5770 TPM2_HANDLE nv_index,
5771 const Tpm2Handle *nv_handle) {
5772
5773 TSS2_RC rc;
5774
5775 assert(c);
5776 assert(nv_handle);
5777
5778 rc = sym_Esys_NV_UndefineSpace(
5779 c->esys_context,
5780 /* authHandle= */ ESYS_TR_RH_OWNER,
5781 /* nvIndex= */ nv_handle->esys_handle,
5782 /* shandle1= */ session ? session->esys_handle : ESYS_TR_NONE,
5783 /* shandle2= */ ESYS_TR_NONE,
5784 /* shandle3= */ ESYS_TR_NONE);
5785 if (rc != TSS2_RC_SUCCESS)
5786 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5787 "Failed to undefine NV index: %s", sym_Tss2_RC_Decode(rc));
5788
5789 log_debug("Undefined NV index 0x%x", nv_index);
5790 return 0;
5791 }
5792
5793 int tpm2_seal_data(
5794 Tpm2Context *c,
5795 const struct iovec *data,
5796 const Tpm2Handle *primary_handle,
5797 const Tpm2Handle *encryption_session,
5798 const TPM2B_DIGEST *policy,
5799 struct iovec *ret_public,
5800 struct iovec *ret_private) {
5801
5802 int r;
5803
5804 assert(c);
5805 assert(data);
5806 assert(primary_handle);
5807
5808 /* This is a generic version of tpm2_seal(), that doesn't imply any policy or any specific
5809 * combination of the two keypairs in their marshalling. tpm2_seal() is somewhat specific to the FDE
5810 * usecase. We probably should migrate tpm2_seal() to use tpm2_seal_data() eventually. */
5811
5812 if (data->iov_len >= sizeof_field(TPMS_SENSITIVE_CREATE, data.buffer))
5813 return -E2BIG;
5814
5815 TPMT_PUBLIC hmac_template = {
5816 .type = TPM2_ALG_KEYEDHASH,
5817 .nameAlg = TPM2_ALG_SHA256,
5818 .objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
5819 .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
5820 .unique.keyedHash.size = data->iov_len,
5821 .authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
5822 };
5823
5824 TPMS_SENSITIVE_CREATE hmac_sensitive = {
5825 .data.size = hmac_template.unique.keyedHash.size,
5826 };
5827
5828 CLEANUP_ERASE(hmac_sensitive);
5829
5830 memcpy_safe(hmac_sensitive.data.buffer, data->iov_base, data->iov_len);
5831
5832 _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
5833 _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
5834 r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
5835 if (r < 0)
5836 return r;
5837
5838 _cleanup_(iovec_done) struct iovec public_blob = {}, private_blob = {};
5839
5840 r = tpm2_marshal_private(private, &private_blob.iov_base, &private_blob.iov_len);
5841 if (r < 0)
5842 return r;
5843
5844 r = tpm2_marshal_public(public, &public_blob.iov_base, &public_blob.iov_len);
5845 if (r < 0)
5846 return r;
5847
5848 if (ret_public)
5849 *ret_public = TAKE_STRUCT(public_blob);
5850 if (ret_private)
5851 *ret_private = TAKE_STRUCT(private_blob);
5852
5853 return 0;
5854 }
5855
5856 int tpm2_unseal_data(
5857 Tpm2Context *c,
5858 const struct iovec *public_blob,
5859 const struct iovec *private_blob,
5860 const Tpm2Handle *primary_handle,
5861 const Tpm2Handle *policy_session,
5862 const Tpm2Handle *encryption_session,
5863 struct iovec *ret_data) {
5864
5865 TSS2_RC rc;
5866 int r;
5867
5868 assert(c);
5869 assert(public_blob);
5870 assert(private_blob);
5871 assert(primary_handle);
5872
5873 TPM2B_PUBLIC public;
5874 r = tpm2_unmarshal_public(public_blob->iov_base, public_blob->iov_len, &public);
5875 if (r < 0)
5876 return r;
5877
5878 TPM2B_PRIVATE private;
5879 r = tpm2_unmarshal_private(private_blob->iov_base, private_blob->iov_len, &private);
5880 if (r < 0)
5881 return r;
5882
5883 _cleanup_(tpm2_handle_freep) Tpm2Handle *what = NULL;
5884 r = tpm2_load(c, primary_handle, NULL, &public, &private, &what);
5885 if (r < 0)
5886 return r;
5887
5888 _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
5889 rc = sym_Esys_Unseal(
5890 c->esys_context,
5891 what->esys_handle,
5892 policy_session ? policy_session->esys_handle : ESYS_TR_NONE,
5893 encryption_session ? encryption_session->esys_handle : ESYS_TR_NONE,
5894 ESYS_TR_NONE,
5895 &unsealed);
5896 if (rc == TPM2_RC_PCR_CHANGED)
5897 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE),
5898 "PCR changed while unsealing.");
5899 if (rc != TSS2_RC_SUCCESS)
5900 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
5901 "Failed to unseal data: %s", sym_Tss2_RC_Decode(rc));
5902
5903 _cleanup_(iovec_done) struct iovec d = {};
5904 d = IOVEC_MAKE(memdup(unsealed->buffer, unsealed->size), unsealed->size);
5905
5906 explicit_bzero_safe(unsealed->buffer, unsealed->size);
5907
5908 if (!d.iov_base)
5909 return log_oom_debug();
5910
5911 *ret_data = TAKE_STRUCT(d);
5912 return 0;
5913 }
5914 #endif /* HAVE_TPM2 */
5915
5916 int tpm2_list_devices(void) {
5917 #if HAVE_TPM2
5918 _cleanup_(table_unrefp) Table *t = NULL;
5919 _cleanup_closedir_ DIR *d = NULL;
5920 int r;
5921
5922 r = dlopen_tpm2();
5923 if (r < 0)
5924 return log_error_errno(r, "TPM2 support is not installed.");
5925
5926 t = table_new("path", "device", "driver");
5927 if (!t)
5928 return log_oom();
5929
5930 d = opendir("/sys/class/tpmrm");
5931 if (!d) {
5932 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open /sys/class/tpmrm: %m");
5933 if (errno != ENOENT)
5934 return -errno;
5935 } else {
5936 for (;;) {
5937 _cleanup_free_ char *device_path = NULL, *device = NULL, *driver_path = NULL, *driver = NULL, *node = NULL;
5938 struct dirent *de;
5939
5940 de = readdir_no_dot(d);
5941 if (!de)
5942 break;
5943
5944 device_path = path_join("/sys/class/tpmrm", de->d_name, "device");
5945 if (!device_path)
5946 return log_oom();
5947
5948 r = readlink_malloc(device_path, &device);
5949 if (r < 0)
5950 log_debug_errno(r, "Failed to read device symlink %s, ignoring: %m", device_path);
5951 else {
5952 driver_path = path_join(device_path, "driver");
5953 if (!driver_path)
5954 return log_oom();
5955
5956 r = readlink_malloc(driver_path, &driver);
5957 if (r < 0)
5958 log_debug_errno(r, "Failed to read driver symlink %s, ignoring: %m", driver_path);
5959 }
5960
5961 node = path_join("/dev", de->d_name);
5962 if (!node)
5963 return log_oom();
5964
5965 r = table_add_many(
5966 t,
5967 TABLE_PATH, node,
5968 TABLE_STRING, device ? last_path_component(device) : NULL,
5969 TABLE_STRING, driver ? last_path_component(driver) : NULL);
5970 if (r < 0)
5971 return table_log_add_error(r);
5972 }
5973 }
5974
5975 if (table_isempty(t)) {
5976 log_info("No suitable TPM2 devices found.");
5977 return 0;
5978 }
5979
5980 r = table_print(t, stdout);
5981 if (r < 0)
5982 return log_error_errno(r, "Failed to show device table: %m");
5983
5984 return 0;
5985 #else
5986 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5987 "TPM2 not supported on this build.");
5988 #endif
5989 }
5990
5991 int tpm2_find_device_auto(char **ret) {
5992 #if HAVE_TPM2
5993 _cleanup_closedir_ DIR *d = NULL;
5994 int r;
5995
5996 r = dlopen_tpm2();
5997 if (r < 0)
5998 return log_debug_errno(r, "TPM2 support is not installed.");
5999
6000 d = opendir("/sys/class/tpmrm");
6001 if (!d) {
6002 log_debug_errno(errno, "Failed to open /sys/class/tpmrm: %m");
6003 if (errno != ENOENT)
6004 return -errno;
6005 } else {
6006 _cleanup_free_ char *node = NULL;
6007
6008 for (;;) {
6009 struct dirent *de;
6010
6011 de = readdir_no_dot(d);
6012 if (!de)
6013 break;
6014
6015 if (node)
6016 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
6017 "More than one TPM2 (tpmrm) device found.");
6018
6019 node = path_join("/dev", de->d_name);
6020 if (!node)
6021 return log_oom_debug();
6022 }
6023
6024 if (node) {
6025 *ret = TAKE_PTR(node);
6026 return 0;
6027 }
6028 }
6029
6030 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "No TPM2 (tpmrm) device found.");
6031 #else
6032 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
6033 "TPM2 not supported on this build.");
6034 #endif
6035 }
6036
6037 #if HAVE_TPM2
6038 static const char* tpm2_userspace_event_type_table[_TPM2_USERSPACE_EVENT_TYPE_MAX] = {
6039 [TPM2_EVENT_PHASE] = "phase",
6040 [TPM2_EVENT_FILESYSTEM] = "filesystem",
6041 [TPM2_EVENT_VOLUME_KEY] = "volume-key",
6042 [TPM2_EVENT_MACHINE_ID] = "machine-id",
6043 };
6044
6045 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
6046
6047 const char *tpm2_userspace_log_path(void) {
6048 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
6049 }
6050
6051 const char *tpm2_firmware_log_path(void) {
6052 return secure_getenv("SYSTEMD_MEASURE_LOG_FIRMWARE") ?: "/sys/kernel/security/tpm0/binary_bios_measurements";
6053 }
6054
6055 #if HAVE_OPENSSL
6056 static int tpm2_userspace_log_open(void) {
6057 _cleanup_close_ int fd = -EBADF;
6058 struct stat st;
6059 const char *e;
6060 int r;
6061
6062 e = tpm2_userspace_log_path();
6063 (void) mkdir_parents(e, 0755);
6064
6065 /* We use access mode 0600 here (even though the measurements should not strictly be confidential),
6066 * because we use BSD file locking on it, and if anyone but root can access the file they can also
6067 * lock it, which we want to avoid. */
6068 fd = open(e, O_CREAT|O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
6069 if (fd < 0)
6070 return log_debug_errno(errno, "Failed to open TPM log file '%s' for writing, ignoring: %m", e);
6071
6072 if (flock(fd, LOCK_EX) < 0)
6073 return log_debug_errno(errno, "Failed to lock TPM log file '%s', ignoring: %m", e);
6074
6075 if (fstat(fd, &st) < 0)
6076 return log_debug_errno(errno, "Failed to fstat TPM log file '%s', ignoring: %m", e);
6077
6078 r = stat_verify_regular(&st);
6079 if (r < 0)
6080 return log_debug_errno(r, "TPM log file '%s' is not regular, ignoring: %m", e);
6081
6082 /* We set the sticky bit when we are about to append to the log file. We'll unset it afterwards
6083 * again. If we manage to take a lock on a file that has it set we know we didn't write it fully and
6084 * it is corrupted. Ideally we'd like to use user xattrs for this, but unfortunately tmpfs (which is
6085 * our assumed backend fs) doesn't know user xattrs. */
6086 if (st.st_mode & S_ISVTX)
6087 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "TPM log file '%s' aborted, ignoring.", e);
6088
6089 if (fchmod(fd, 0600 | S_ISVTX) < 0)
6090 return log_debug_errno(errno, "Failed to chmod() TPM log file '%s', ignoring: %m", e);
6091
6092 return TAKE_FD(fd);
6093 }
6094
6095 static int tpm2_userspace_log(
6096 int fd,
6097 unsigned pcr_index,
6098 const TPML_DIGEST_VALUES *values,
6099 Tpm2UserspaceEventType event_type,
6100 const char *description) {
6101
6102 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *array = NULL;
6103 _cleanup_free_ char *f = NULL;
6104 sd_id128_t boot_id;
6105 int r;
6106
6107 assert(values);
6108 assert(values->count > 0);
6109
6110 /* We maintain a local PCR measurement log. This implements a subset of the TCG Canonical Event Log
6111 * Format – the JSON flavour –
6112 * (https://trustedcomputinggroup.org/resource/canonical-event-log-format/), but departs in certain
6113 * ways from it, specifically:
6114 *
6115 * - We don't write out a recnum. It's a bit too vaguely defined which means we'd have to read
6116 * through the whole logs (include firmware logs) before knowing what the next value is we should
6117 * use. Hence we simply don't write this out as append-time, and instead expect a consumer to add
6118 * it in when it uses the data.
6119 *
6120 * - We write this out in RFC 7464 application/json-seq rather than as a JSON array. Writing this as
6121 * JSON array would mean that for each appending we'd have to read the whole log file fully into
6122 * memory before writing it out again. We prefer a strictly append-only write pattern however. (RFC
6123 * 7464 is what jq --seq eats.) Conversion into a proper JSON array is trivial.
6124 *
6125 * It should be possible to convert this format in a relatively straight-forward way into the
6126 * official TCG Canonical Event Log Format on read, by simply adding in a few more fields that can be
6127 * determined from the full dataset.
6128 *
6129 * We set the 'content_type' field to "systemd" to make clear this data is generated by us, and
6130 * include various interesting fields in the 'content' subobject, including a CLOCK_BOOTTIME
6131 * timestamp which can be used to order this measurement against possibly other measurements
6132 * independently done by other subsystems on the system.
6133 */
6134
6135 if (fd < 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
6136 return 0;
6137
6138 for (size_t i = 0; i < values->count; i++) {
6139 const EVP_MD *implementation;
6140 const char *a;
6141
6142 assert_se(a = tpm2_hash_alg_to_string(values->digests[i].hashAlg));
6143 assert_se(implementation = EVP_get_digestbyname(a));
6144
6145 r = json_variant_append_arrayb(
6146 &array, JSON_BUILD_OBJECT(
6147 JSON_BUILD_PAIR_STRING("hashAlg", a),
6148 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(&values->digests[i].digest, EVP_MD_size(implementation)))));
6149 if (r < 0)
6150 return log_debug_errno(r, "Failed to append digest object to JSON array: %m");
6151 }
6152
6153 assert(array);
6154
6155 r = sd_id128_get_boot(&boot_id);
6156 if (r < 0)
6157 return log_debug_errno(r, "Failed to acquire boot ID: %m");
6158
6159 r = json_build(&v, JSON_BUILD_OBJECT(
6160 JSON_BUILD_PAIR("pcr", JSON_BUILD_UNSIGNED(pcr_index)),
6161 JSON_BUILD_PAIR("digests", JSON_BUILD_VARIANT(array)),
6162 JSON_BUILD_PAIR("content_type", JSON_BUILD_STRING("systemd")),
6163 JSON_BUILD_PAIR("content", JSON_BUILD_OBJECT(
6164 JSON_BUILD_PAIR_CONDITION(description, "string", JSON_BUILD_STRING(description)),
6165 JSON_BUILD_PAIR("bootId", JSON_BUILD_ID128(boot_id)),
6166 JSON_BUILD_PAIR("timestamp", JSON_BUILD_UNSIGNED(now(CLOCK_BOOTTIME))),
6167 JSON_BUILD_PAIR_CONDITION(event_type >= 0, "eventType", JSON_BUILD_STRING(tpm2_userspace_event_type_to_string(event_type)))))));
6168 if (r < 0)
6169 return log_debug_errno(r, "Failed to build log record JSON: %m");
6170
6171 r = json_variant_format(v, JSON_FORMAT_SEQ, &f);
6172 if (r < 0)
6173 return log_debug_errno(r, "Failed to format JSON: %m");
6174
6175 if (lseek(fd, 0, SEEK_END) < 0)
6176 return log_debug_errno(errno, "Failed to seek to end of JSON log: %m");
6177
6178 r = loop_write(fd, f, SIZE_MAX);
6179 if (r < 0)
6180 return log_debug_errno(r, "Failed to write JSON data to log: %m");
6181
6182 if (fsync(fd) < 0)
6183 return log_debug_errno(errno, "Failed to sync JSON data: %m");
6184
6185 /* Unset S_ISVTX again */
6186 if (fchmod(fd, 0600) < 0)
6187 return log_debug_errno(errno, "Failed to chmod() TPM log file, ignoring: %m");
6188
6189 r = fsync_full(fd);
6190 if (r < 0)
6191 return log_debug_errno(r, "Failed to sync JSON log: %m");
6192
6193 return 1;
6194 }
6195 #endif
6196
6197 int tpm2_extend_bytes(
6198 Tpm2Context *c,
6199 char **banks,
6200 unsigned pcr_index,
6201 const void *data,
6202 size_t data_size,
6203 const void *secret,
6204 size_t secret_size,
6205 Tpm2UserspaceEventType event_type,
6206 const char *description) {
6207
6208 #if HAVE_OPENSSL
6209 _cleanup_close_ int log_fd = -EBADF;
6210 TPML_DIGEST_VALUES values = {};
6211 TSS2_RC rc;
6212
6213 assert(c);
6214 assert(data || data_size == 0);
6215 assert(secret || secret_size == 0);
6216
6217 if (data_size == SIZE_MAX)
6218 data_size = strlen(data);
6219 if (secret_size == SIZE_MAX)
6220 secret_size = strlen(secret);
6221
6222 if (pcr_index >= TPM2_PCRS_MAX)
6223 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index);
6224
6225 if (strv_isempty(banks))
6226 return 0;
6227
6228 STRV_FOREACH(bank, banks) {
6229 const EVP_MD *implementation;
6230 int id;
6231
6232 assert_se(implementation = EVP_get_digestbyname(*bank));
6233
6234 if (values.count >= ELEMENTSOF(values.digests))
6235 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected.");
6236
6237 if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest))
6238 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2.");
6239
6240 id = tpm2_hash_alg_from_string(EVP_MD_name(implementation));
6241 if (id < 0)
6242 return log_debug_errno(id, "Can't map hash name to TPM2.");
6243
6244 values.digests[values.count].hashAlg = id;
6245
6246 /* So here's a twist: sometimes we want to measure secrets (e.g. root file system volume
6247 * key), but we'd rather not leak a literal hash of the secret to the TPM (given that the
6248 * wire is unprotected, and some other subsystem might use the simple, literal hash of the
6249 * secret for other purposes, maybe because it needs a shorter secret derived from it for
6250 * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a
6251 * private non-secret string instead. */
6252 if (secret_size > 0) {
6253 if (!HMAC(implementation, secret, secret_size, data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL))
6254 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure.");
6255 } else if (EVP_Digest(data, data_size, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1)
6256 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure.");
6257
6258 values.count++;
6259 }
6260
6261 /* Open + lock the log file *before* we start measuring, so that no one else can come between our log
6262 * and our measurement and change either */
6263 log_fd = tpm2_userspace_log_open();
6264
6265 rc = sym_Esys_PCR_Extend(
6266 c->esys_context,
6267 ESYS_TR_PCR0 + pcr_index,
6268 ESYS_TR_PASSWORD,
6269 ESYS_TR_NONE,
6270 ESYS_TR_NONE,
6271 &values);
6272 if (rc != TSS2_RC_SUCCESS)
6273 return log_debug_errno(
6274 SYNTHETIC_ERRNO(ENOTRECOVERABLE),
6275 "Failed to measure into PCR %u: %s",
6276 pcr_index,
6277 sym_Tss2_RC_Decode(rc));
6278
6279 /* Now, write what we just extended to the log, too. */
6280 (void) tpm2_userspace_log(log_fd, pcr_index, &values, event_type, description);
6281
6282 return 0;
6283 #else /* HAVE_OPENSSL */
6284 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
6285 #endif
6286 }
6287
6288 const uint16_t tpm2_hash_algorithms[] = {
6289 TPM2_ALG_SHA1,
6290 TPM2_ALG_SHA256,
6291 TPM2_ALG_SHA384,
6292 TPM2_ALG_SHA512,
6293 0,
6294 };
6295
6296 assert_cc(ELEMENTSOF(tpm2_hash_algorithms) == TPM2_N_HASH_ALGORITHMS + 1);
6297
6298 static size_t tpm2_hash_algorithm_index(uint16_t algorithm) {
6299 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++)
6300 if (tpm2_hash_algorithms[i] == algorithm)
6301 return i;
6302
6303 return SIZE_MAX;
6304 }
6305
6306 TPM2B_DIGEST *tpm2_pcr_prediction_result_get_hash(Tpm2PCRPredictionResult *result, uint16_t alg) {
6307 size_t alg_idx;
6308
6309 assert(result);
6310
6311 alg_idx = tpm2_hash_algorithm_index(alg);
6312 if (alg_idx == SIZE_MAX) /* Algorithm not known? */
6313 return NULL;
6314
6315 if (result->hash[alg_idx].size <= 0) /* No hash value for this algorithm? */
6316 return NULL;
6317
6318 return result->hash + alg_idx;
6319 }
6320
6321 void tpm2_pcr_prediction_done(Tpm2PCRPrediction *p) {
6322 assert(p);
6323
6324 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++)
6325 ordered_set_free(p->results[pcr]);
6326 }
6327
6328 static void tpm2_pcr_prediction_result_hash_func(const Tpm2PCRPredictionResult *banks, struct siphash *state) {
6329 assert(banks);
6330
6331 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++)
6332 siphash24_compress_safe(banks->hash[i].buffer, banks->hash[i].size, state);
6333 }
6334
6335 static int tpm2_pcr_prediction_result_compare_func(const Tpm2PCRPredictionResult *a, const Tpm2PCRPredictionResult *b) {
6336 int r;
6337
6338 assert(a);
6339 assert(b);
6340
6341 for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++) {
6342 r = memcmp_nn(a->hash[i].buffer, a->hash[i].size,
6343 b->hash[i].buffer, b->hash[i].size);
6344 if (r != 0)
6345 return r;
6346 }
6347
6348 return 0;
6349 }
6350
6351 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
6352 tpm2_pcr_prediction_result_hash_ops,
6353 Tpm2PCRPredictionResult,
6354 tpm2_pcr_prediction_result_hash_func,
6355 tpm2_pcr_prediction_result_compare_func,
6356 Tpm2PCRPredictionResult,
6357 free);
6358
6359 static Tpm2PCRPredictionResult *find_prediction_result_by_algorithm(OrderedSet *set, Tpm2PCRPredictionResult *result, size_t alg_idx) {
6360 Tpm2PCRPredictionResult *f;
6361
6362 assert(result);
6363 assert(alg_idx != SIZE_MAX);
6364
6365 f = ordered_set_get(set, result); /* Full match? */
6366 if (f)
6367 return f;
6368
6369 /* If this doesn't match full, then see if there an entry that at least matches by the relevant
6370 * algorithm (we are fine if predictions are "incomplete" in some algorithms) */
6371
6372 ORDERED_SET_FOREACH(f, set)
6373 if (memcmp_nn(result->hash[alg_idx].buffer, result->hash[alg_idx].size,
6374 f->hash[alg_idx].buffer, f->hash[alg_idx].size) == 0)
6375 return f;
6376
6377 return NULL;
6378 }
6379
6380 bool tpm2_pcr_prediction_equal(
6381 Tpm2PCRPrediction *a,
6382 Tpm2PCRPrediction *b,
6383 uint16_t algorithm) {
6384
6385 if (a == b)
6386 return true;
6387 if (!a || !b)
6388 return false;
6389
6390 if (a->pcrs != b->pcrs)
6391 return false;
6392
6393 size_t alg_idx = tpm2_hash_algorithm_index(algorithm);
6394 if (alg_idx == SIZE_MAX)
6395 return false;
6396
6397 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6398 Tpm2PCRPredictionResult *banks;
6399
6400 ORDERED_SET_FOREACH(banks, a->results[pcr])
6401 if (!find_prediction_result_by_algorithm(b->results[pcr], banks, alg_idx))
6402 return false;
6403
6404 ORDERED_SET_FOREACH(banks, b->results[pcr])
6405 if (!find_prediction_result_by_algorithm(a->results[pcr], banks, alg_idx))
6406 return false;
6407 }
6408
6409 return true;
6410 }
6411
6412 int tpm2_pcr_prediction_to_json(
6413 const Tpm2PCRPrediction *prediction,
6414 uint16_t algorithm,
6415 JsonVariant **ret) {
6416
6417 _cleanup_(json_variant_unrefp) JsonVariant *aj = NULL;
6418 int r;
6419
6420 assert(prediction);
6421 assert(ret);
6422
6423 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6424 _cleanup_(json_variant_unrefp) JsonVariant *vj = NULL;
6425 Tpm2PCRPredictionResult *banks;
6426
6427 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6428 continue;
6429
6430 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6431
6432 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6433 if (!hash)
6434 continue;
6435
6436 r = json_variant_append_arrayb(
6437 &vj,
6438 JSON_BUILD_HEX(hash->buffer, hash->size));
6439 if (r < 0)
6440 return log_error_errno(r, "Failed to append hash variant to JSON array: %m");
6441 }
6442
6443 if (!vj)
6444 continue;
6445
6446 r = json_variant_append_arrayb(
6447 &aj,
6448 JSON_BUILD_OBJECT(
6449 JSON_BUILD_PAIR_INTEGER("pcr", pcr),
6450 JSON_BUILD_PAIR_VARIANT("values", vj)));
6451 if (r < 0)
6452 return log_error_errno(r, "Failed to append PCR variants to JSON array: %m");
6453 }
6454
6455 if (!aj) {
6456 r = json_variant_new_array(&aj, NULL, 0);
6457 if (r < 0)
6458 return r;
6459 }
6460
6461 *ret = TAKE_PTR(aj);
6462 return 0;
6463 }
6464
6465 int tpm2_pcr_prediction_from_json(
6466 Tpm2PCRPrediction *prediction,
6467 uint16_t algorithm,
6468 JsonVariant *aj) {
6469
6470 int r;
6471
6472 assert(prediction);
6473
6474 size_t alg_index = tpm2_hash_algorithm_index(algorithm);
6475 assert(alg_index < TPM2_N_HASH_ALGORITHMS);
6476
6477 if (!json_variant_is_array(aj))
6478 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR variant array is not an array.");
6479
6480 JsonVariant *pcr;
6481 JSON_VARIANT_ARRAY_FOREACH(pcr, aj) {
6482 JsonVariant *nr, *values;
6483
6484 nr = json_variant_by_key(pcr, "pcr");
6485 if (!nr)
6486 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry lacks PCR index field");
6487
6488 if (!json_variant_is_unsigned(nr) ||
6489 json_variant_unsigned(nr) >= TPM2_PCRS_MAX)
6490 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry PCR index is not an integer in the range 0…23");
6491
6492 values = json_variant_by_key(pcr, "values");
6493 if (!values)
6494 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry lacks values field");
6495
6496 if (!json_variant_is_array(values))
6497 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PCR array entry values field is not an array");
6498
6499 prediction->pcrs |= UINT32_C(1) << json_variant_unsigned(nr);
6500
6501 JsonVariant *v;
6502 JSON_VARIANT_ARRAY_FOREACH(v, values) {
6503 _cleanup_free_ void *buffer = NULL;
6504 size_t size;
6505
6506 r = json_variant_unhex(v, &buffer, &size);
6507 if (r < 0)
6508 return log_error_errno(r, "Failed to decode PCR policy array hash value");
6509
6510 if (size <= 0)
6511 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PCR policy array hash value is zero.");
6512
6513 if (size > sizeof_field(TPM2B_DIGEST, buffer))
6514 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PCR policy array hash value is too large.");
6515
6516 _cleanup_free_ Tpm2PCRPredictionResult *banks = new0(Tpm2PCRPredictionResult, 1);
6517 if (!banks)
6518 return log_oom();
6519
6520 memcpy(banks->hash[alg_index].buffer, buffer, size);
6521 banks->hash[alg_index].size = size;
6522
6523 r = ordered_set_ensure_put(prediction->results + json_variant_unsigned(nr), &tpm2_pcr_prediction_result_hash_ops, banks);
6524 if (r == -EEXIST) /* Let's allow duplicates */
6525 continue;
6526 if (r < 0)
6527 return log_error_errno(r, "Failed to insert result into set: %m");
6528
6529 TAKE_PTR(banks);
6530 }
6531 }
6532
6533 return 0;
6534 }
6535
6536 int tpm2_calculate_policy_super_pcr(
6537 Tpm2PCRPrediction *prediction,
6538 uint16_t algorithm,
6539 TPM2B_DIGEST *pcr_policy) {
6540
6541 int r;
6542
6543 assert_se(prediction);
6544 assert_se(pcr_policy);
6545
6546 /* Start with a zero policy if not specified otherwise. */
6547 TPM2B_DIGEST super_pcr_policy_digest = *pcr_policy;
6548
6549 /* First we look for all PCRs that have exactly one allowed hash value, and generate a single PolicyPCR policy from them */
6550 _cleanup_free_ Tpm2PCRValue *single_values = NULL;
6551 size_t n_single_values = 0;
6552 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6553 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6554 continue;
6555
6556 if (ordered_set_size(prediction->results[pcr]) != 1)
6557 continue;
6558
6559 log_debug("Including PCR %" PRIu32 " in single value PolicyPCR expression", pcr);
6560
6561 Tpm2PCRPredictionResult *banks = ASSERT_PTR(ordered_set_first(prediction->results[pcr]));
6562
6563 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6564 if (!hash)
6565 continue;
6566
6567 if (!GREEDY_REALLOC(single_values, n_single_values + 1))
6568 return -ENOMEM;
6569
6570 single_values[n_single_values++] = TPM2_PCR_VALUE_MAKE(pcr, algorithm, *hash);
6571 }
6572
6573 if (n_single_values > 0) {
6574 /* Evolve policy based on the expected PCR value for what we found. */
6575 r = tpm2_calculate_policy_pcr(
6576 single_values,
6577 n_single_values,
6578 &super_pcr_policy_digest);
6579 if (r < 0)
6580 return r;
6581 }
6582
6583 /* Now deal with the PCRs for which we have variants, i.e. more than one allowed values */
6584 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6585 _cleanup_free_ TPM2B_DIGEST *pcr_policy_digest_variants = NULL;
6586 size_t n_pcr_policy_digest_variants = 0;
6587 Tpm2PCRPredictionResult *banks;
6588
6589 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6590 continue;
6591
6592 if (ordered_set_size(prediction->results[pcr]) <= 1) /* We only care for PCRs with 2 or more variants in this loop */
6593 continue;
6594
6595 if (ordered_set_size(prediction->results[pcr]) > 8)
6596 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "PCR policies with more than 8 alternatives per PCR are currently not supported.");
6597
6598 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6599 /* Start from the super PCR policy from the previous PCR we looked at so far. */
6600 TPM2B_DIGEST pcr_policy_digest = super_pcr_policy_digest;
6601
6602 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6603 if (!hash)
6604 continue;
6605
6606 /* Evolve it based on the expected PCR value for this PCR */
6607 r = tpm2_calculate_policy_pcr(
6608 &TPM2_PCR_VALUE_MAKE(
6609 pcr,
6610 algorithm,
6611 *hash),
6612 /* n_pcr_values= */ 1,
6613 &pcr_policy_digest);
6614 if (r < 0)
6615 return r;
6616
6617 /* Store away this new variant */
6618 if (!GREEDY_REALLOC(pcr_policy_digest_variants, n_pcr_policy_digest_variants + 1))
6619 return log_oom();
6620
6621 pcr_policy_digest_variants[n_pcr_policy_digest_variants++] = pcr_policy_digest;
6622
6623 log_debug("Calculated PCR policy variant %zu for PCR %" PRIu32, n_pcr_policy_digest_variants, pcr);
6624 }
6625
6626 assert_se(n_pcr_policy_digest_variants >= 2);
6627 assert_se(n_pcr_policy_digest_variants <= 8);
6628
6629 /* Now combine all our variant into one OR policy */
6630 r = tpm2_calculate_policy_or(
6631 pcr_policy_digest_variants,
6632 n_pcr_policy_digest_variants,
6633 &super_pcr_policy_digest);
6634 if (r < 0)
6635 return r;
6636
6637 log_debug("Combined %zu variants in OR policy.", n_pcr_policy_digest_variants);
6638 }
6639
6640 *pcr_policy = super_pcr_policy_digest;
6641 return 0;
6642 }
6643
6644 int tpm2_policy_super_pcr(
6645 Tpm2Context *c,
6646 const Tpm2Handle *session,
6647 const Tpm2PCRPrediction *prediction,
6648 uint16_t algorithm) {
6649
6650 int r;
6651
6652 assert_se(c);
6653 assert_se(session);
6654 assert_se(prediction);
6655
6656 TPM2B_DIGEST previous_policy_digest = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
6657
6658 uint32_t single_value_pcrs = 0;
6659
6660 /* Look for all PCRs that have only a singled allowed hash value, and synthesize a single PolicyPCR policy item for them */
6661 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6662 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6663 continue;
6664
6665 if (ordered_set_size(prediction->results[pcr]) != 1)
6666 continue;
6667
6668 log_debug("Including PCR %" PRIu32 " in single value PolicyPCR expression", pcr);
6669
6670 single_value_pcrs |= UINT32_C(1) << pcr;
6671 }
6672
6673 if (single_value_pcrs != 0) {
6674 TPML_PCR_SELECTION pcr_selection;
6675 tpm2_tpml_pcr_selection_from_mask(single_value_pcrs, algorithm, &pcr_selection);
6676
6677 _cleanup_free_ TPM2B_DIGEST *current_policy_digest = NULL;
6678 r = tpm2_policy_pcr(
6679 c,
6680 session,
6681 &pcr_selection,
6682 &current_policy_digest);
6683 if (r < 0)
6684 return r;
6685
6686 previous_policy_digest = *current_policy_digest;
6687 }
6688
6689 for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) {
6690 size_t n_branches;
6691
6692 if (!FLAGS_SET(prediction->pcrs, UINT32_C(1) << pcr))
6693 continue;
6694
6695 n_branches = ordered_set_size(prediction->results[pcr]);
6696 if (n_branches < 1 || n_branches > 8)
6697 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Number of variants per PCR not in range 1…8");
6698
6699 if (n_branches == 1) /* Single choice PCRs are already covered by the loop above */
6700 continue;
6701
6702 log_debug("Submitting PCR/OR policy for PCR %" PRIu32, pcr);
6703
6704 TPML_PCR_SELECTION pcr_selection;
6705 tpm2_tpml_pcr_selection_from_mask(UINT32_C(1) << pcr, algorithm, &pcr_selection);
6706
6707 _cleanup_free_ TPM2B_DIGEST *current_policy_digest = NULL;
6708 r = tpm2_policy_pcr(
6709 c,
6710 session,
6711 &pcr_selection,
6712 &current_policy_digest);
6713 if (r < 0)
6714 return r;
6715
6716 _cleanup_free_ TPM2B_DIGEST *branches = NULL;
6717 branches = new0(TPM2B_DIGEST, n_branches);
6718 if (!branches)
6719 return log_oom();
6720
6721 Tpm2PCRPredictionResult *banks;
6722 size_t i = 0;
6723 ORDERED_SET_FOREACH(banks, prediction->results[pcr]) {
6724 TPM2B_DIGEST pcr_policy_digest = previous_policy_digest;
6725
6726 TPM2B_DIGEST *hash = tpm2_pcr_prediction_result_get_hash(banks, algorithm);
6727 if (!hash)
6728 continue;
6729
6730 /* Evolve it based on the expected PCR value for this PCR */
6731 r = tpm2_calculate_policy_pcr(
6732 &TPM2_PCR_VALUE_MAKE(
6733 pcr,
6734 algorithm,
6735 *hash),
6736 /* n_pcr_values= */ 1,
6737 &pcr_policy_digest);
6738 if (r < 0)
6739 return r;
6740
6741 branches[i++] = pcr_policy_digest;
6742 }
6743
6744 assert_se(i == n_branches);
6745
6746 current_policy_digest = mfree(current_policy_digest);
6747 r = tpm2_policy_or(
6748 c,
6749 session,
6750 branches,
6751 n_branches,
6752 &current_policy_digest);
6753 if (r < 0)
6754 return r;
6755
6756 previous_policy_digest = *current_policy_digest;
6757 }
6758
6759 return 0;
6760 }
6761
6762 void tpm2_pcrlock_policy_done(Tpm2PCRLockPolicy *data) {
6763 assert(data);
6764
6765 data->prediction_json = json_variant_unref(data->prediction_json);
6766 tpm2_pcr_prediction_done(&data->prediction);
6767 iovec_done(&data->nv_handle);
6768 iovec_done(&data->nv_public);
6769 iovec_done(&data->srk_handle);
6770 iovec_done(&data->pin_public);
6771 iovec_done(&data->pin_private);
6772 }
6773
6774 static int json_dispatch_tpm2_algorithm(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
6775 uint16_t *algorithm = ASSERT_PTR(userdata);
6776 int r;
6777
6778 r = tpm2_hash_alg_from_string(json_variant_string(variant));
6779 if (r < 0 || tpm2_hash_algorithm_index(r) == SIZE_MAX)
6780 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid hash algorithm: %s", json_variant_string(variant));
6781
6782 *algorithm = r;
6783 return 0;
6784 }
6785
6786 int tpm2_pcrlock_search_file(const char *path, FILE **ret_file, char **ret_path) {
6787 static const char search[] =
6788 "/run/systemd\0"
6789 "/var/lib/systemd\0";
6790
6791 int r;
6792
6793 if (!path)
6794 path = "pcrlock.json";
6795
6796 r = search_and_fopen_nulstr(path, ret_file ? "re" : NULL, NULL, search, ret_file, ret_path);
6797 if (r < 0)
6798 return log_debug_errno(r, "Failed to find TPM2 pcrlock policy file '%s': %m", path);
6799
6800 return 0;
6801 }
6802
6803 int tpm2_pcrlock_policy_load(
6804 const char *path,
6805 Tpm2PCRLockPolicy *ret_policy) {
6806
6807 _cleanup_free_ char *discovered_path = NULL;
6808 _cleanup_fclose_ FILE *f = NULL;
6809 int r;
6810
6811 r = tpm2_pcrlock_search_file(path, &f, &discovered_path);
6812 if (r == -ENOENT) {
6813 *ret_policy = (Tpm2PCRLockPolicy) {};
6814 return 0;
6815 }
6816 if (r < 0)
6817 return log_error_errno(r, "Failed to load TPM2 pcrlock policy file: %m");
6818
6819 _cleanup_(json_variant_unrefp) JsonVariant *configuration_json = NULL;
6820 r = json_parse_file(
6821 f,
6822 discovered_path,
6823 /* flags = */ 0,
6824 &configuration_json,
6825 /* ret_line= */ NULL,
6826 /* ret_column= */ NULL);
6827 if (r < 0)
6828 return log_error_errno(r, "Failed to parse existing pcrlock policy file '%s': %m", discovered_path);
6829
6830 JsonDispatch policy_dispatch[] = {
6831 { "pcrBank", JSON_VARIANT_STRING, json_dispatch_tpm2_algorithm, offsetof(Tpm2PCRLockPolicy, algorithm), JSON_MANDATORY },
6832 { "pcrValues", JSON_VARIANT_ARRAY, json_dispatch_variant, offsetof(Tpm2PCRLockPolicy, prediction_json), JSON_MANDATORY },
6833 { "nvIndex", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint32, offsetof(Tpm2PCRLockPolicy, nv_index), JSON_MANDATORY },
6834 { "nvHandle", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, nv_handle), JSON_MANDATORY },
6835 { "nvPublic", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, nv_public), JSON_MANDATORY },
6836 { "srkHandle", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, srk_handle), JSON_MANDATORY },
6837 { "pinPublic", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, pin_public), JSON_MANDATORY },
6838 { "pinPrivate", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(Tpm2PCRLockPolicy, pin_private), JSON_MANDATORY },
6839 {}
6840 };
6841
6842 _cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy policy = {};
6843
6844 r = json_dispatch(configuration_json, policy_dispatch, JSON_LOG, &policy);
6845 if (r < 0)
6846 return r;
6847
6848 r = tpm2_pcr_prediction_from_json(&policy.prediction, policy.algorithm, policy.prediction_json);
6849 if (r < 0)
6850 return r;
6851
6852 *ret_policy = TAKE_STRUCT(policy);
6853 return 1;
6854 }
6855
6856 int tpm2_load_public_key_file(const char *path, TPM2B_PUBLIC *ret) {
6857 _cleanup_free_ char *device_key_buffer = NULL;
6858 TPM2B_PUBLIC device_key_public = {};
6859 size_t device_key_buffer_size;
6860 TSS2_RC rc;
6861 int r;
6862
6863 assert(path);
6864 assert(ret);
6865
6866 r = dlopen_tpm2();
6867 if (r < 0)
6868 return log_debug_errno(r, "TPM2 support not installed: %m");
6869
6870 r = read_full_file(path, &device_key_buffer, &device_key_buffer_size);
6871 if (r < 0)
6872 return log_error_errno(r, "Failed to read device key from file '%s': %m", path);
6873
6874 size_t offset = 0;
6875 rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(
6876 (uint8_t*) device_key_buffer,
6877 device_key_buffer_size,
6878 &offset,
6879 &device_key_public);
6880 if (rc != TSS2_RC_SUCCESS)
6881 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6882 "Could not unmarshal public key from file.");
6883
6884 assert(offset <= device_key_buffer_size);
6885 if (offset != device_key_buffer_size)
6886 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6887 "Found %zu bytes of trailing garbage in public key file.",
6888 device_key_buffer_size - offset);
6889
6890 *ret = device_key_public;
6891 return 0;
6892 }
6893 #endif
6894
6895 char *tpm2_pcr_mask_to_string(uint32_t mask) {
6896 _cleanup_free_ char *s = NULL;
6897
6898 FOREACH_PCR_IN_MASK(n, mask)
6899 if (strextendf_with_separator(&s, "+", "%d", n) < 0)
6900 return NULL;
6901
6902 if (!s)
6903 return strdup("");
6904
6905 return TAKE_PTR(s);
6906 }
6907
6908 int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
6909 _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
6910 int r;
6911
6912 assert(ret);
6913
6914 for (size_t i = 0; i < TPM2_PCRS_MAX; i++) {
6915 _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
6916
6917 if ((pcr_mask & (UINT32_C(1) << i)) == 0)
6918 continue;
6919
6920 r = json_variant_new_integer(&e, i);
6921 if (r < 0)
6922 return r;
6923
6924 r = json_variant_append_array(&a, e);
6925 if (r < 0)
6926 return r;
6927 }
6928
6929 if (!a)
6930 return json_variant_new_array(ret, NULL, 0);
6931
6932 *ret = TAKE_PTR(a);
6933 return 0;
6934 }
6935
6936 int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
6937 JsonVariant *e;
6938 uint32_t mask = 0;
6939
6940 if (!json_variant_is_array(v))
6941 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
6942
6943 JSON_VARIANT_ARRAY_FOREACH(e, v) {
6944 uint64_t u;
6945
6946 if (!json_variant_is_unsigned(e))
6947 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
6948
6949 u = json_variant_unsigned(e);
6950 if (u >= TPM2_PCRS_MAX)
6951 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
6952
6953 mask |= UINT32_C(1) << u;
6954 }
6955
6956 if (ret)
6957 *ret = mask;
6958
6959 return 0;
6960 }
6961
6962 int tpm2_make_luks2_json(
6963 int keyslot,
6964 uint32_t hash_pcr_mask,
6965 uint16_t pcr_bank,
6966 const struct iovec *pubkey,
6967 uint32_t pubkey_pcr_mask,
6968 uint16_t primary_alg,
6969 const struct iovec *blob,
6970 const struct iovec *policy_hash,
6971 const struct iovec *salt,
6972 const struct iovec *srk,
6973 TPM2Flags flags,
6974 JsonVariant **ret) {
6975
6976 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL;
6977 _cleanup_free_ char *keyslot_as_string = NULL;
6978 int r;
6979
6980 assert(iovec_is_valid(pubkey));
6981 assert(iovec_is_valid(blob));
6982 assert(iovec_is_valid(policy_hash));
6983
6984 if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
6985 return -ENOMEM;
6986
6987 r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj);
6988 if (r < 0)
6989 return r;
6990
6991 if (pubkey_pcr_mask != 0) {
6992 r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj);
6993 if (r < 0)
6994 return r;
6995 }
6996
6997 /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with
6998 * other programming languages. Let's not make things worse though, i.e. future additions to the JSON
6999 * object should use "_" rather than "-" in field names. */
7000
7001 r = json_build(&v,
7002 JSON_BUILD_OBJECT(
7003 JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
7004 JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
7005 JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_IOVEC_BASE64(blob)),
7006 JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
7007 JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
7008 JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg))),
7009 JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_IOVEC_HEX(policy_hash)),
7010 JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
7011 JSON_BUILD_PAIR("tpm2_pcrlock", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PCRLOCK)),
7012 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
7013 JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_IOVEC_BASE64(pubkey)),
7014 JSON_BUILD_PAIR_CONDITION(iovec_is_set(salt), "tpm2_salt", JSON_BUILD_IOVEC_BASE64(salt)),
7015 JSON_BUILD_PAIR_CONDITION(iovec_is_set(srk), "tpm2_srk", JSON_BUILD_IOVEC_BASE64(srk))));
7016 if (r < 0)
7017 return r;
7018
7019 if (ret)
7020 *ret = TAKE_PTR(v);
7021
7022 return keyslot;
7023 }
7024
7025 int tpm2_parse_luks2_json(
7026 JsonVariant *v,
7027 int *ret_keyslot,
7028 uint32_t *ret_hash_pcr_mask,
7029 uint16_t *ret_pcr_bank,
7030 struct iovec *ret_pubkey,
7031 uint32_t *ret_pubkey_pcr_mask,
7032 uint16_t *ret_primary_alg,
7033 struct iovec *ret_blob,
7034 struct iovec *ret_policy_hash,
7035 struct iovec *ret_salt,
7036 struct iovec *ret_srk,
7037 TPM2Flags *ret_flags) {
7038
7039 _cleanup_(iovec_done) struct iovec blob = {}, policy_hash = {}, pubkey = {}, salt = {}, srk = {};
7040 uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
7041 uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
7042 uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
7043 int r, keyslot = -1;
7044 TPM2Flags flags = 0;
7045 JsonVariant *w;
7046
7047 assert(v);
7048
7049 if (ret_keyslot) {
7050 keyslot = cryptsetup_get_keyslot_from_token(v);
7051 if (keyslot < 0) {
7052 /* Return a recognizable error when parsing this field, so that callers can handle parsing
7053 * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
7054 * spec */
7055 log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
7056 return -EUCLEAN;
7057 }
7058 }
7059
7060 w = json_variant_by_key(v, "tpm2-pcrs");
7061 if (!w)
7062 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
7063
7064 r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
7065 if (r < 0)
7066 return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
7067
7068 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
7069 * to SHA256. */
7070 w = json_variant_by_key(v, "tpm2-pcr-bank");
7071 if (w) {
7072 /* The PCR bank field is optional */
7073
7074 if (!json_variant_is_string(w))
7075 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
7076
7077 r = tpm2_hash_alg_from_string(json_variant_string(w));
7078 if (r < 0)
7079 return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
7080
7081 pcr_bank = r;
7082 }
7083
7084 /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
7085 * the algorithm was hardcoded to ECC. */
7086 w = json_variant_by_key(v, "tpm2-primary-alg");
7087 if (w) {
7088 /* The primary key algorithm is optional */
7089
7090 if (!json_variant_is_string(w))
7091 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
7092
7093 r = tpm2_asym_alg_from_string(json_variant_string(w));
7094 if (r < 0)
7095 return log_debug_errno(r, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w));
7096
7097 primary_alg = r;
7098 }
7099
7100 w = json_variant_by_key(v, "tpm2-blob");
7101 if (!w)
7102 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
7103
7104 r = json_variant_unbase64_iovec(w, &blob);
7105 if (r < 0)
7106 return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
7107
7108 w = json_variant_by_key(v, "tpm2-policy-hash");
7109 if (!w)
7110 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
7111
7112 r = json_variant_unhex_iovec(w, &policy_hash);
7113 if (r < 0)
7114 return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
7115
7116 w = json_variant_by_key(v, "tpm2-pin");
7117 if (w) {
7118 if (!json_variant_is_boolean(w))
7119 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
7120
7121 SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
7122 }
7123
7124 w = json_variant_by_key(v, "tpm2_pcrlock");
7125 if (w) {
7126 if (!json_variant_is_boolean(w))
7127 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 pclock policy is not a boolean.");
7128
7129 SET_FLAG(flags, TPM2_FLAGS_USE_PCRLOCK, json_variant_boolean(w));
7130 }
7131
7132 w = json_variant_by_key(v, "tpm2_salt");
7133 if (w) {
7134 r = json_variant_unbase64_iovec(w, &salt);
7135 if (r < 0)
7136 return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
7137 }
7138
7139 w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
7140 if (w) {
7141 r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
7142 if (r < 0)
7143 return r;
7144 }
7145
7146 w = json_variant_by_key(v, "tpm2_pubkey");
7147 if (w) {
7148 r = json_variant_unbase64_iovec(w, &pubkey);
7149 if (r < 0)
7150 return log_debug_errno(r, "Failed to decode PCR public key.");
7151 } else if (pubkey_pcr_mask != 0)
7152 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
7153
7154 w = json_variant_by_key(v, "tpm2_srk");
7155 if (w) {
7156 r = json_variant_unbase64_iovec(w, &srk);
7157 if (r < 0)
7158 return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
7159 }
7160
7161 if (ret_keyslot)
7162 *ret_keyslot = keyslot;
7163 if (ret_hash_pcr_mask)
7164 *ret_hash_pcr_mask = hash_pcr_mask;
7165 if (ret_pcr_bank)
7166 *ret_pcr_bank = pcr_bank;
7167 if (ret_pubkey)
7168 *ret_pubkey = TAKE_STRUCT(pubkey);
7169 if (ret_pubkey_pcr_mask)
7170 *ret_pubkey_pcr_mask = pubkey_pcr_mask;
7171 if (ret_primary_alg)
7172 *ret_primary_alg = primary_alg;
7173 if (ret_blob)
7174 *ret_blob = TAKE_STRUCT(blob);
7175 if (ret_policy_hash)
7176 *ret_policy_hash = TAKE_STRUCT(policy_hash);
7177 if (ret_salt)
7178 *ret_salt = TAKE_STRUCT(salt);
7179 if (ret_flags)
7180 *ret_flags = flags;
7181 if (ret_srk)
7182 *ret_srk = TAKE_STRUCT(srk);
7183
7184 return 0;
7185 }
7186
7187 int tpm2_hash_alg_to_size(uint16_t alg) {
7188 switch (alg) {
7189 case TPM2_ALG_SHA1:
7190 return 20;
7191 case TPM2_ALG_SHA256:
7192 return 32;
7193 case TPM2_ALG_SHA384:
7194 return 48;
7195 case TPM2_ALG_SHA512:
7196 return 64;
7197 default:
7198 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm id 0x%" PRIx16, alg);
7199 }
7200 }
7201
7202 const char *tpm2_hash_alg_to_string(uint16_t alg) {
7203 switch (alg) {
7204 case TPM2_ALG_SHA1:
7205 return "sha1";
7206 case TPM2_ALG_SHA256:
7207 return "sha256";
7208 case TPM2_ALG_SHA384:
7209 return "sha384";
7210 case TPM2_ALG_SHA512:
7211 return "sha512";
7212 default:
7213 log_debug("Unknown hash algorithm id 0x%" PRIx16, alg);
7214 return NULL;
7215 }
7216 }
7217
7218 int tpm2_hash_alg_from_string(const char *alg) {
7219 if (strcaseeq_ptr(alg, "sha1"))
7220 return TPM2_ALG_SHA1;
7221 if (strcaseeq_ptr(alg, "sha256"))
7222 return TPM2_ALG_SHA256;
7223 if (strcaseeq_ptr(alg, "sha384"))
7224 return TPM2_ALG_SHA384;
7225 if (strcaseeq_ptr(alg, "sha512"))
7226 return TPM2_ALG_SHA512;
7227 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown hash algorithm name '%s'", alg);
7228 }
7229
7230 const char *tpm2_asym_alg_to_string(uint16_t alg) {
7231 switch (alg) {
7232 case TPM2_ALG_ECC:
7233 return "ecc";
7234 case TPM2_ALG_RSA:
7235 return "rsa";
7236 default:
7237 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16, alg);
7238 return NULL;
7239 }
7240 }
7241
7242 int tpm2_asym_alg_from_string(const char *alg) {
7243 if (strcaseeq_ptr(alg, "ecc"))
7244 return TPM2_ALG_ECC;
7245 if (strcaseeq_ptr(alg, "rsa"))
7246 return TPM2_ALG_RSA;
7247 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown asymmetric algorithm name '%s'", alg);
7248 }
7249
7250 const char *tpm2_sym_alg_to_string(uint16_t alg) {
7251 switch (alg) {
7252 #if HAVE_TPM2
7253 case TPM2_ALG_AES:
7254 return "aes";
7255 #endif
7256 default:
7257 log_debug("Unknown symmetric algorithm id 0x%" PRIx16, alg);
7258 return NULL;
7259 }
7260 }
7261
7262 int tpm2_sym_alg_from_string(const char *alg) {
7263 #if HAVE_TPM2
7264 if (strcaseeq_ptr(alg, "aes"))
7265 return TPM2_ALG_AES;
7266 #endif
7267 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric algorithm name '%s'", alg);
7268 }
7269
7270 const char *tpm2_sym_mode_to_string(uint16_t mode) {
7271 switch (mode) {
7272 #if HAVE_TPM2
7273 case TPM2_ALG_CTR:
7274 return "ctr";
7275 case TPM2_ALG_OFB:
7276 return "ofb";
7277 case TPM2_ALG_CBC:
7278 return "cbc";
7279 case TPM2_ALG_CFB:
7280 return "cfb";
7281 case TPM2_ALG_ECB:
7282 return "ecb";
7283 #endif
7284 default:
7285 log_debug("Unknown symmetric mode id 0x%" PRIx16, mode);
7286 return NULL;
7287 }
7288 }
7289
7290 int tpm2_sym_mode_from_string(const char *mode) {
7291 #if HAVE_TPM2
7292 if (strcaseeq_ptr(mode, "ctr"))
7293 return TPM2_ALG_CTR;
7294 if (strcaseeq_ptr(mode, "ofb"))
7295 return TPM2_ALG_OFB;
7296 if (strcaseeq_ptr(mode, "cbc"))
7297 return TPM2_ALG_CBC;
7298 if (strcaseeq_ptr(mode, "cfb"))
7299 return TPM2_ALG_CFB;
7300 if (strcaseeq_ptr(mode, "ecb"))
7301 return TPM2_ALG_ECB;
7302 #endif
7303 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric mode name '%s'", mode);
7304 }
7305
7306 Tpm2Support tpm2_support(void) {
7307 Tpm2Support support = TPM2_SUPPORT_NONE;
7308 int r;
7309
7310 if (detect_container() <= 0) {
7311 /* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
7312 * got the host sysfs mounted. Since devices are generally not virtualized for containers,
7313 * let's assume containers never have a TPM, at least for now. */
7314
7315 r = dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
7316 if (r < 0) {
7317 if (r != -ENOENT)
7318 log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
7319 } else if (r == 0) /* populated! */
7320 support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
7321 else
7322 /* If the directory exists but is empty, we know the subsystem is enabled but no
7323 * driver has been loaded yet. */
7324 support |= TPM2_SUPPORT_SUBSYSTEM;
7325 }
7326
7327 if (efi_has_tpm2())
7328 support |= TPM2_SUPPORT_FIRMWARE;
7329
7330 #if HAVE_TPM2
7331 support |= TPM2_SUPPORT_SYSTEM;
7332
7333 r = dlopen_tpm2();
7334 if (r >= 0)
7335 support |= TPM2_SUPPORT_LIBRARIES;
7336 #endif
7337
7338 return support;
7339 }
7340
7341 #if HAVE_TPM2
7342 static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
7343 TPMI_ALG_HASH default_hash = 0;
7344 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
7345 if (v->hash != 0) {
7346 default_hash = v->hash;
7347 break;
7348 }
7349
7350 if (default_hash != 0)
7351 FOREACH_ARRAY(v, pcr_values, n_pcr_values)
7352 if (v->hash == 0)
7353 v->hash = default_hash;
7354 }
7355 #endif
7356
7357 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
7358 * parse_*_argument() functions. */
7359
7360 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
7361 *
7362 * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
7363 * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
7364 * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
7365 *
7366 * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
7367 * tpm2_parse_pcr_argument_append(). */
7368 int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
7369 #if HAVE_TPM2
7370 int r;
7371
7372 assert(arg);
7373 assert(ret_pcr_values);
7374 assert(ret_n_pcr_values);
7375
7376 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
7377 size_t n_pcr_values = 0;
7378 r = tpm2_pcr_values_from_string(arg, &pcr_values, &n_pcr_values);
7379 if (r < 0)
7380 return log_error_errno(r, "Could not parse PCR values from '%s': %m", arg);
7381
7382 tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
7383
7384 tpm2_sort_pcr_values(pcr_values, n_pcr_values);
7385
7386 if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
7387 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
7388
7389 *ret_pcr_values = TAKE_PTR(pcr_values);
7390 *ret_n_pcr_values = n_pcr_values;
7391
7392 return 0;
7393 #else
7394 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7395 #endif
7396 }
7397
7398 /* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
7399 * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
7400 * must be correct.
7401 *
7402 * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
7403 * including application of the default hash algorithm. Then the two arrays are combined, the default hash
7404 * algorithm check applied again (in case either the previous or current array had no default hash
7405 * algorithm), and then the resulting array is sorted and rechecked for validity. */
7406 int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values) {
7407 #if HAVE_TPM2
7408 int r;
7409
7410 assert(arg);
7411 assert(pcr_values);
7412 assert(n_pcr_values);
7413
7414 _cleanup_free_ Tpm2PCRValue *more_pcr_values = NULL;
7415 size_t n_more_pcr_values;
7416 r = tpm2_parse_pcr_argument(arg, &more_pcr_values, &n_more_pcr_values);
7417 if (r < 0)
7418 return r;
7419
7420 /* If we got previous values, append them. */
7421 if (*pcr_values && !GREEDY_REALLOC_APPEND(more_pcr_values, n_more_pcr_values, *pcr_values, *n_pcr_values))
7422 return log_oom();
7423
7424 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values, n_more_pcr_values);
7425
7426 tpm2_sort_pcr_values(more_pcr_values, n_more_pcr_values);
7427
7428 if (!tpm2_pcr_values_valid(more_pcr_values, n_more_pcr_values))
7429 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
7430
7431 SWAP_TWO(*pcr_values, more_pcr_values);
7432 *n_pcr_values = n_more_pcr_values;
7433
7434 return 0;
7435 #else
7436 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7437 #endif
7438 }
7439
7440 /* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
7441 * algorithm is included in the pcr values array this results in error. This retains the previous behavior of
7442 * tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
7443 * UINT32_MAX, and or-ing the mask otherwise. */
7444 int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *ret_mask) {
7445 #if HAVE_TPM2
7446 _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
7447 size_t n_pcr_values;
7448 int r;
7449
7450 assert(arg);
7451 assert(ret_mask);
7452
7453 r = tpm2_parse_pcr_argument(arg, &pcr_values, &n_pcr_values);
7454 if (r < 0)
7455 return r;
7456
7457 if (n_pcr_values == 0) {
7458 /* This retains the previous behavior of clearing the mask if the arg is empty */
7459 *ret_mask = 0;
7460 return 0;
7461 }
7462
7463 size_t hash_count;
7464 r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
7465 if (r < 0)
7466 return log_error_errno(r, "Could not get hash count from pcr values: %m");
7467
7468 if (hash_count > 1)
7469 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR hash banks selected.");
7470
7471 uint32_t new_mask;
7472 r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
7473 if (r < 0)
7474 return log_error_errno(r, "Could not get pcr values mask: %m");
7475
7476 if (*ret_mask == UINT32_MAX)
7477 *ret_mask = new_mask;
7478 else
7479 *ret_mask |= new_mask;
7480
7481 return 0;
7482 #else
7483 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
7484 #endif
7485 }
7486
7487 int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
7488 _cleanup_strv_free_ char **search = NULL;
7489 _cleanup_free_ char *discovered_path = NULL;
7490 _cleanup_fclose_ FILE *f = NULL;
7491 int r;
7492
7493 /* Tries to load a JSON PCR signature file. Takes an absolute path, a simple file name or NULL. In
7494 * the latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7495
7496 search = strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
7497 if (!search)
7498 return log_oom_debug();
7499
7500 if (!path) {
7501 /* If no path is specified, then look for "tpm2-pcr-signature.json" automatically. Also, in
7502 * this case include /.extra/ in the search path, but only in this case, and if we run in the
7503 * initrd. We don't want to be too eager here, after all /.extra/ is untrusted territory. */
7504
7505 path = "tpm2-pcr-signature.json";
7506
7507 if (in_initrd())
7508 if (strv_extend(&search, "/.extra") < 0)
7509 return log_oom_debug();
7510 }
7511
7512 r = search_and_fopen(path, "re", NULL, (const char**) search, &f, &discovered_path);
7513 if (r < 0)
7514 return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path);
7515
7516 r = json_parse_file(f, discovered_path, 0, ret, NULL, NULL);
7517 if (r < 0)
7518 return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path);
7519
7520 return 0;
7521 }
7522
7523 int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size) {
7524 _cleanup_free_ char *discovered_path = NULL;
7525 _cleanup_fclose_ FILE *f = NULL;
7526 int r;
7527
7528 /* Tries to load a PCR public key file. Takes an absolute path, a simple file name or NULL. In the
7529 * latter two cases searches in /etc/, /usr/lib/, /run/, as usual. */
7530
7531 if (!path)
7532 path = "tpm2-pcr-public-key.pem";
7533
7534 r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("systemd"), &f, &discovered_path);
7535 if (r < 0)
7536 return log_debug_errno(r, "Failed to find TPM PCR public key file '%s': %m", path);
7537
7538 r = read_full_stream(f, (char**) ret_pubkey, ret_pubkey_size);
7539 if (r < 0)
7540 return log_debug_errno(r, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path);
7541
7542 return 0;
7543 }
7544
7545 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
7546
7547 /*
7548 * Implements PBKDF2 HMAC SHA256 for a derived keylen of 32
7549 * bytes and for PBKDF2_HMAC_SHA256_ITERATIONS count.
7550 * I found the wikipedia entry relevant and it contains links to
7551 * relevant RFCs:
7552 * - https://en.wikipedia.org/wiki/PBKDF2
7553 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
7554 */
7555 int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
7556 size_t passlen,
7557 const void *salt,
7558 size_t saltlen,
7559 uint8_t ret_key[static SHA256_DIGEST_SIZE]) {
7560
7561 _cleanup_(erase_and_freep) uint8_t *buffer = NULL;
7562 uint8_t u[SHA256_DIGEST_SIZE];
7563
7564 /* To keep this simple, since derived KeyLen (dkLen in docs)
7565 * Is the same as the hash output, we don't need multiple
7566 * blocks. Part of the algorithm is to add the block count
7567 * in, but this can be hardcoded to 1.
7568 */
7569 static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
7570
7571 assert (salt);
7572 assert (saltlen > 0);
7573 assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
7574 assert (passlen > 0);
7575
7576 /*
7577 * Build a buffer of salt + block_cnt and hmac_sha256 it we
7578 * do this as we don't have a context builder for HMAC_SHA256.
7579 */
7580 buffer = malloc(saltlen + sizeof(block_cnt));
7581 if (!buffer)
7582 return -ENOMEM;
7583
7584 memcpy(buffer, salt, saltlen);
7585 memcpy(&buffer[saltlen], block_cnt, sizeof(block_cnt));
7586
7587 hmac_sha256(pass, passlen, buffer, saltlen + sizeof(block_cnt), u);
7588
7589 /* dk needs to be an unmodified u as u gets modified in the loop */
7590 memcpy(ret_key, u, SHA256_DIGEST_SIZE);
7591 uint8_t *dk = ret_key;
7592
7593 for (size_t i = 1; i < PBKDF2_HMAC_SHA256_ITERATIONS; i++) {
7594 hmac_sha256(pass, passlen, u, sizeof(u), u);
7595
7596 for (size_t j=0; j < sizeof(u); j++)
7597 dk[j] ^= u[j];
7598 }
7599
7600 return 0;
7601 }
7602
7603 static const char* const tpm2_pcr_index_table[_TPM2_PCR_INDEX_MAX_DEFINED] = {
7604 [TPM2_PCR_PLATFORM_CODE] = "platform-code",
7605 [TPM2_PCR_PLATFORM_CONFIG] = "platform-config",
7606 [TPM2_PCR_EXTERNAL_CODE] = "external-code",
7607 [TPM2_PCR_EXTERNAL_CONFIG] = "external-config",
7608 [TPM2_PCR_BOOT_LOADER_CODE] = "boot-loader-code",
7609 [TPM2_PCR_BOOT_LOADER_CONFIG] = "boot-loader-config",
7610 [TPM2_PCR_HOST_PLATFORM] = "host-platform",
7611 [TPM2_PCR_SECURE_BOOT_POLICY] = "secure-boot-policy",
7612 [TPM2_PCR_KERNEL_INITRD] = "kernel-initrd",
7613 [TPM2_PCR_IMA] = "ima",
7614 [TPM2_PCR_KERNEL_BOOT] = "kernel-boot",
7615 [TPM2_PCR_KERNEL_CONFIG] = "kernel-config",
7616 [TPM2_PCR_SYSEXTS] = "sysexts",
7617 [TPM2_PCR_SHIM_POLICY] = "shim-policy",
7618 [TPM2_PCR_SYSTEM_IDENTITY] = "system-identity",
7619 [TPM2_PCR_DEBUG] = "debug",
7620 [TPM2_PCR_APPLICATION_SUPPORT] = "application-support",
7621 };
7622
7623 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index, int, TPM2_PCRS_MAX - 1);
7624 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index, int);