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