1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "creds-util.h"
8 #include "cryptsetup-util.h"
9 #include "dirent-util.h"
10 #include "dlfcn-util.h"
12 #include "extract-word.h"
15 #include "format-table.h"
17 #include "hexdecoct.h"
19 #include "initrd-util.h"
21 #include "lock-util.h"
23 #include "logarithm.h"
24 #include "memory-util.h"
26 #include "nulstr-util.h"
27 #include "parse-util.h"
28 #include "random-util.h"
29 #include "recurse-dir.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"
40 static void *libtss2_esys_dl
= NULL
;
41 static void *libtss2_rc_dl
= NULL
;
42 static void *libtss2_mu_dl
= NULL
;
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
;
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
;
104 static const char* (*sym_Tss2_RC_Decode
)(TSS2_RC rc
) = NULL
;
106 int dlopen_tpm2(void) {
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
));
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
));
156 log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
158 r
= dlopen_many_sym_or_warn(
159 &libtss2_rc_dl
, "libtss2-rc.so.0", LOG_DEBUG
,
160 DLSYM_ARG(Tss2_RC_Decode
));
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
));
187 void Esys_Freep(void *p
) {
189 sym_Esys_Free(*(void**) p
);
192 /* Get a specific TPM capability (or capabilities).
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).
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
207 static int tpm2_get_capability(
212 TPMU_CAPABILITIES
*ret_capability_data
) {
214 _cleanup_(Esys_Freep
) TPMS_CAPABILITY_DATA
*capabilities
= NULL
;
220 log_debug("Getting TPM2 capability 0x%04" PRIx32
" property 0x%04" PRIx32
" count %" PRIu32
".",
221 capability
, property
, count
);
223 rc
= sym_Esys_GetCapability(
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
);
246 if (ret_capability_data
)
247 *ret_capability_data
= capabilities
->data
;
249 return more
== TPM2_YES
;
252 #define TPMA_CC_TO_TPM2_CC(cca) (((cca) & TPMA_CC_COMMANDINDEX_MASK) >> TPMA_CC_COMMANDINDEX_SHIFT)
254 static int tpm2_cache_capabilities(Tpm2Context
*c
) {
255 TPMU_CAPABILITIES capability
;
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
;
269 r
= tpm2_get_capability(
272 (uint32_t) current_alg
, /* The spec states to cast TPM2_ALG_ID to uint32_t. */
278 TPML_ALG_PROPERTY algorithms
= capability
.algorithms
;
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);
284 if (!GREEDY_REALLOC_APPEND(
285 c
->capability_algorithms
,
286 c
->n_capability_algorithms
,
287 algorithms
.algProperties
,
289 return log_oom_debug();
294 /* Set current_alg to alg id after last alg id the TPM provided */
295 current_alg
= algorithms
.algProperties
[algorithms
.count
- 1].alg
+ 1;
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
;
302 r
= tpm2_get_capability(
311 TPML_CCA commands
= capability
.command
;
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);
317 if (!GREEDY_REALLOC_APPEND(
318 c
->capability_commands
,
319 c
->n_capability_commands
,
320 commands
.commandAttributes
,
322 return log_oom_debug();
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;
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
;
335 r
= tpm2_get_capability(
341 if (r
== -ENXIO
) /* If the TPM doesn't support ECC, it might return TPM2_RC_VALUE rather than capability.eccCurves == 0 */
346 TPML_ECC_CURVE ecc_curves
= capability
.eccCurves
;
348 /* ECC support isn't required */
349 if (ecc_curves
.count
== 0)
352 if (!GREEDY_REALLOC_APPEND(
353 c
->capability_ecc_curves
,
354 c
->n_capability_ecc_curves
,
355 ecc_curves
.eccCurves
,
357 return log_oom_debug();
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;
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(
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
;
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
) {
394 FOREACH_ARRAY(alg_prop
, c
->capability_algorithms
, c
->n_capability_algorithms
)
395 if (alg_prop
->alg
== alg
) {
397 *ret
= alg_prop
->algProperties
;
401 log_debug("TPM does not support alg 0x%02" PRIx16
".", alg
);
408 bool tpm2_supports_alg(Tpm2Context
*c
, TPM2_ALG_ID alg
) {
409 return tpm2_get_capability_alg(c
, alg
, NULL
);
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
) {
417 FOREACH_ARRAY(cca
, c
->capability_commands
, c
->n_capability_commands
)
418 if (TPMA_CC_TO_TPM2_CC(*cca
) == command
) {
424 log_debug("TPM does not support command 0x%04" PRIx32
".", command
);
431 bool tpm2_supports_command(Tpm2Context
*c
, TPM2_CC command
) {
432 return tpm2_get_capability_command(c
, command
, NULL
);
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
) {
439 FOREACH_ARRAY(curve
, c
->capability_ecc_curves
, c
->n_capability_ecc_curves
)
440 if (*curve
== ecc_curve
)
443 log_debug("TPM does not support ECC curve 0x%" PRIx16
".", ecc_curve
);
447 /* Query the TPM for populated handles.
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).
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(
460 TPM2_HANDLE
**ret_handles
,
461 size_t *ret_n_handles
) {
463 _cleanup_free_ TPM2_HANDLE
*handles
= NULL
;
464 size_t n_handles
= 0;
465 TPM2_HANDLE current
= start
;
470 assert(ret_n_handles
);
472 max
= MIN(max
, UINT32_MAX
);
475 TPMU_CAPABILITIES capability
;
476 r
= tpm2_get_capability(c
, TPM2_CAP_HANDLES
, current
, (uint32_t) max
, &capability
);
480 TPML_HANDLE handle_list
= capability
.handles
;
481 if (handle_list
.count
== 0)
484 assert(handle_list
.count
<= max
);
486 if (n_handles
> SIZE_MAX
- handle_list
.count
)
487 return log_oom_debug();
489 if (!GREEDY_REALLOC_APPEND(handles
, n_handles
, handle_list
.handle
, handle_list
.count
))
490 return log_oom_debug();
492 max
-= handle_list
.count
;
494 /* Update current to the handle index after the last handle in the list. */
495 current
= handles
[n_handles
- 1] + 1;
498 /* No more handles in this range. */
502 *ret_handles
= TAKE_PTR(handles
);
503 *ret_n_handles
= n_handles
;
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))
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;
517 r
= tpm2_get_capability_handles(c
, handle
, 1, &handles
, &n_handles
);
521 return n_handles
== 0 ? false : handles
[0] == handle
;
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
) {
531 TPMT_PUBLIC_PARMS parameters
= {
533 .parameters
= *parms
,
536 rc
= sym_Esys_TestParms(c
->esys_context
, ESYS_TR_NONE
, ESYS_TR_NONE
, ESYS_TR_NONE
, ¶meters
);
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
));
544 return rc
== TSS2_RC_SUCCESS
;
547 static bool tpm2_supports_tpmt_public(Tpm2Context
*c
, const TPMT_PUBLIC
*public) {
551 return tpm2_test_parms(c
, public->type
, &public->parameters
);
554 static bool tpm2_supports_tpmt_sym_def_object(Tpm2Context
*c
, const TPMT_SYM_DEF_OBJECT
*parameters
) {
558 TPMU_PUBLIC_PARMS parms
= {
559 .symDetail
.sym
= *parameters
,
562 return tpm2_test_parms(c
, TPM2_ALG_SYMCIPHER
, &parms
);
565 static bool tpm2_supports_tpmt_sym_def(Tpm2Context
*c
, const TPMT_SYM_DEF
*parameters
) {
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
,
577 return tpm2_supports_tpmt_sym_def_object(c
, &object
);
580 static Tpm2Context
*tpm2_context_free(Tpm2Context
*c
) {
585 sym_Esys_Finalize(&c
->esys_context
);
587 c
->tcti_context
= mfree(c
->tcti_context
);
588 c
->tcti_dl
= safe_dlclose(c
->tcti_dl
);
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
);
597 DEFINE_TRIVIAL_REF_UNREF_FUNC(Tpm2Context
, tpm2_context
, tpm2_context_free
);
599 static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB
= {
600 .algorithm
= TPM2_ALG_AES
,
602 .mode
.aes
= TPM2_ALG_CFB
, /* The spec requires sessions to use CFB. */
605 int tpm2_context_new(const char *device
, Tpm2Context
**ret_context
) {
606 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= NULL
;
612 context
= new(Tpm2Context
, 1);
614 return log_oom_debug();
616 *context
= (Tpm2Context
) {
622 return log_debug_errno(r
, "TPM2 support not installed: %m");
625 device
= secure_getenv("SYSTEMD_TPM2_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
);
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";
639 const char *param
, *driver
, *fn
;
640 const TSS2_TCTI_INFO
* info
;
641 TSS2_TCTI_INFO_FUNC func
;
644 param
= strchr(device
, ':');
646 /* Syntax #1: Pair of driver string and arbitrary parameter */
647 driver
= strndupa_safe(device
, param
- device
);
649 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 driver name is empty, refusing.");
652 } else if (path_is_absolute(device
) && path_is_valid(device
)) {
653 /* Syntax #2: TPM device node */
657 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid TPM2 driver string, refusing.");
659 log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver
, param
);
661 fn
= strjoina("libtss2-tcti-", driver
, ".so.0");
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
);
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());
671 func
= dlsym(context
->tcti_dl
, TSS2_TCTI_INFO_SYMBOL
);
673 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
674 "Failed to find TCTI info symbol " TSS2_TCTI_INFO_SYMBOL
": %s",
679 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Unable to get TCTI info data.");
681 log_debug("Loaded TCTI module '%s' (%s) [Version %" PRIu32
"]", info
->name
, info
->description
, info
->version
);
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
));
688 context
->tcti_context
= malloc0(sz
);
689 if (!context
->tcti_context
)
690 return log_oom_debug();
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
));
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
));
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.");
709 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
710 "Failed to start up TPM: %s", sym_Tss2_RC_Decode(rc
));
712 r
= tpm2_cache_capabilities(context
);
714 return log_debug_errno(r
, "Failed to cache TPM capabilities: %m");
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.");
720 if (!tpm2_supports_alg(context
, TPM2_ALG_CFB
))
721 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM does not support CFB.");
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.");
726 *ret_context
= TAKE_PTR(context
);
731 static void tpm2_handle_cleanup(ESYS_CONTEXT
*esys_context
, ESYS_TR esys_handle
, bool flush
) {
734 if (!esys_context
|| esys_handle
== ESYS_TR_NONE
)
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. */
741 rc
= sym_Esys_FlushContext(esys_context
, esys_handle
);
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.
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
));
762 Tpm2Handle
*tpm2_handle_free(Tpm2Handle
*handle
) {
766 _cleanup_(tpm2_context_unrefp
) Tpm2Context
*context
= (Tpm2Context
*)handle
->tpm2_context
;
768 tpm2_handle_cleanup(context
->esys_context
, handle
->esys_handle
, handle
->flush
);
770 return mfree(handle
);
773 int tpm2_handle_new(Tpm2Context
*context
, Tpm2Handle
**ret_handle
) {
774 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
778 handle
= new(Tpm2Handle
, 1);
780 return log_oom_debug();
782 *handle
= (Tpm2Handle
) {
783 .tpm2_context
= tpm2_context_ref(context
),
784 .esys_handle
= ESYS_TR_NONE
,
788 *ret_handle
= TAKE_PTR(handle
);
793 static int tpm2_read_public(
795 const Tpm2Handle
*session
,
796 const Tpm2Handle
*handle
,
797 TPM2B_PUBLIC
**ret_public
,
798 TPM2B_NAME
**ret_name
,
799 TPM2B_NAME
**ret_qname
) {
806 rc
= sym_Esys_ReadPublic(
809 session
? session
->esys_handle
: ESYS_TR_NONE
,
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
));
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
827 int tpm2_index_to_handle(
830 const Tpm2Handle
*session
,
831 TPM2B_PUBLIC
**ret_public
,
832 TPM2B_NAME
**ret_name
,
833 TPM2B_NAME
**ret_qname
,
834 Tpm2Handle
**ret_handle
) {
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
:
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
);
861 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
862 "Invalid handle 0x%08" PRIx32
" (in unknown range).", index
);
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
);
873 log_debug("TPM handle 0x%08" PRIx32
" not populated.", index
);
886 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
887 r
= tpm2_handle_new(c
, &handle
);
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;
895 rc
= sym_Esys_TR_FromTPMPublic(
898 session
? session
->esys_handle
: 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
));
906 if (ret_public
|| ret_name
|| ret_qname
) {
907 r
= tpm2_read_public(c
, session
, handle
, ret_public
, ret_name
, ret_qname
);
913 *ret_handle
= TAKE_PTR(handle
);
918 /* Get the handle index for the provided Tpm2Handle. */
919 int tpm2_index_from_handle(Tpm2Context
*c
, const Tpm2Handle
*handle
, TPM2_HANDLE
*ret_index
) {
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.");
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
));
940 /* Copy an object in the TPM at a transient handle to a persistent handle.
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
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).
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(
958 const Tpm2Handle
*transient_handle
,
959 const Tpm2Handle
*session
,
960 TPMI_DH_PERSISTENT persistent_handle_index
,
961 Tpm2Handle
**ret_persistent_handle
) {
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);
970 assert(transient_handle
);
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
);
978 first
= last
= persistent_handle_index
;
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
);
987 /* Since this is a persistent handle, don't flush it. */
988 persistent_handle
->flush
= false;
990 rc
= sym_Esys_EvictControl(
993 transient_handle
->esys_handle
,
994 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
998 &persistent_handle
->esys_handle
);
999 if (rc
== TSS2_RC_SUCCESS
) {
1000 if (ret_persistent_handle
)
1001 *ret_persistent_handle
= TAKE_PTR(persistent_handle
);
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
));
1010 if (ret_persistent_handle
)
1011 *ret_persistent_handle
= NULL
;
1016 #define TPM2_CREDIT_RANDOM_FLAG_PATH "/run/systemd/tpm-rng-credited"
1018 static int tpm2_credit_random(Tpm2Context
*c
) {
1019 size_t rps
, done
= 0;
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
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");
1035 log_debug("Not adding TPM2 entropy to the kernel random pool again.");
1036 return 0; /* Already done */
1039 t
= now(CLOCK_MONOTONIC
);
1041 for (rps
= random_pool_size(); rps
> 0;) {
1042 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*buffer
= NULL
;
1044 rc
= sym_Esys_GetRandom(
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. */
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
));
1055 if (buffer
->size
== 0)
1056 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
1057 "Zero-sized entropy returned from TPM.");
1059 r
= random_write_entropy(-1, buffer
->buffer
, buffer
->size
, /* credit= */ false);
1061 return log_debug_errno(r
, "Failed wo write entropy to kernel: %m");
1063 done
+= buffer
->size
;
1064 rps
= LESS_BY(rps
, buffer
->size
);
1067 log_debug("Added %zu bytes of TPM2 entropy to the kernel random pool in %s.", done
, FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - t
, 0));
1069 r
= touch(TPM2_CREDIT_RANDOM_FLAG_PATH
);
1071 log_debug_errno(r
, "Failed to touch '" TPM2_CREDIT_RANDOM_FLAG_PATH
"', ignoring: %m");
1076 /* Get one of the legacy primary key templates.
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
,
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
= {
1096 .algorithm
= TPM2_ALG_AES
,
1098 .mode
.aes
= TPM2_ALG_CFB
,
1100 .scheme
.scheme
= TPM2_ALG_NULL
,
1101 .curveID
= TPM2_ECC_NIST_P256
,
1102 .kdf
.scheme
= TPM2_ALG_NULL
,
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
= {
1113 .algorithm
= TPM2_ALG_AES
,
1115 .mode
.aes
= TPM2_ALG_CFB
,
1117 .scheme
.scheme
= TPM2_ALG_NULL
,
1122 assert(ret_template
);
1124 if (alg
== TPM2_ALG_ECC
)
1125 *ret_template
= legacy_ecc
;
1126 else if (alg
== TPM2_ALG_RSA
)
1127 *ret_template
= legacy_rsa
;
1129 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1130 "Unsupported legacy SRK alg: 0x%x", alg
);
1135 /* Get a Storage Root Key (SRK) template.
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
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
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).
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
|
1162 TPMA_OBJECT_RESTRICTED
|
1163 TPMA_OBJECT_SENSITIVEDATAORIGIN
|
1164 TPMA_OBJECT_USERWITHAUTH
;
1166 /* The symmetric configuration is the same between ECC and RSA templates. */
1167 TPMT_SYM_DEF_OBJECT srk_symmetric
= {
1168 .algorithm
= TPM2_ALG_AES
,
1170 .mode
.aes
= TPM2_ALG_CFB
,
1173 /* Both templates have an empty authPolicy as specified by the Provisioning Guidance document. */
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
,
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
,
1200 assert(ret_template
);
1204 *ret_template
= srk_ecc
;
1207 *ret_template
= srk_rsa
;
1211 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "No SRK for algorithm 0x%" PRIx16
, alg
);
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;
1220 assert(ret_template
);
1222 r
= tpm2_get_srk_template(TPM2_ALG_ECC
, &template);
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.");
1233 *ret_template
= template;
1237 r
= tpm2_get_srk_template(TPM2_ALG_RSA
, &template);
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.");
1246 *ret_template
= template;
1250 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1251 "TPM does not support either SRK template L-1 (RSA) or L-2 (ECC).");
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. */
1258 const Tpm2Handle
*session
,
1259 TPM2B_PUBLIC
**ret_public
,
1260 TPM2B_NAME
**ret_name
,
1261 TPM2B_NAME
**ret_qname
,
1262 Tpm2Handle
**ret_handle
) {
1264 return tpm2_index_to_handle(c
, TPM2_SRK_HANDLE
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
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(
1271 const Tpm2Handle
*session
,
1272 TPM2B_PUBLIC
**ret_public
,
1273 TPM2B_NAME
**ret_name
,
1274 TPM2B_NAME
**ret_qname
,
1275 Tpm2Handle
**ret_handle
) {
1279 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1283 return 0; /* 0 → SRK already set up */
1285 /* No SRK, create and persist one */
1286 TPM2B_PUBLIC
template = {
1287 .size
= sizeof(TPMT_PUBLIC
),
1289 r
= tpm2_get_best_srk_template(c
, &template.publicArea
);
1291 return log_debug_errno(r
, "Could not get best SRK template: %m");
1293 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*transient_handle
= NULL
;
1294 r
= tpm2_create_primary(
1298 /* sensitive= */ NULL
,
1299 /* ret_public= */ NULL
,
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
);
1311 /* The SRK should exist now. */
1312 r
= tpm2_get_srk(c
, session
, ret_public
, ret_name
, ret_qname
, ret_handle
);
1316 /* This should never happen. */
1317 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "SRK we just persisted couldn't be found.");
1319 return 1; /* > 0 → SRK newly set up */
1322 /* Utility functions for TPMS_PCR_SELECTION. */
1324 /* Convert a TPMS_PCR_SELECTION object to a mask. */
1325 uint32_t tpm2_tpms_pcr_selection_to_mask(const TPMS_PCR_SELECTION
*s
) {
1327 assert(s
->sizeofSelect
<= sizeof(s
->pcrSelect
));
1330 for (unsigned i
= 0; i
< s
->sizeofSelect
; i
++)
1331 SET_FLAG(mask
, (uint32_t)s
->pcrSelect
[i
] << (i
* 8), true);
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
) {
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
));
1344 *ret
= (TPMS_PCR_SELECTION
){
1346 .sizeofSelect
= TPM2_PCRS_MAX
/ 8,
1347 .pcrSelect
[0] = mask
& 0xff,
1348 .pcrSelect
[1] = (mask
>> 8) & 0xff,
1349 .pcrSelect
[2] = (mask
>> 16) & 0xff,
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
) {
1357 return FLAGS_SET(tpm2_tpms_pcr_selection_to_mask(s
), mask
);
1360 static void tpm2_tpms_pcr_selection_update_mask(TPMS_PCR_SELECTION
*s
, uint32_t mask
, bool b
) {
1363 tpm2_tpms_pcr_selection_from_mask(UPDATE_FLAG(tpm2_tpms_pcr_selection_to_mask(s
), mask
, b
), s
->hash
, s
);
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);
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);
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
) {
1380 assert(a
->hash
== b
->hash
);
1382 tpm2_tpms_pcr_selection_add_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
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
) {
1389 assert(a
->hash
== b
->hash
);
1391 tpm2_tpms_pcr_selection_sub_mask(a
, tpm2_tpms_pcr_selection_to_mask(b
));
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
) {
1399 tpm2_tpms_pcr_selection_add(a
, b
);
1400 tpm2_tpms_pcr_selection_from_mask(0, b
->hash
, b
);
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)
1409 #define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
1410 FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
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)
1416 char *tpm2_tpms_pcr_selection_to_string(const TPMS_PCR_SELECTION
*s
) {
1419 const char *algstr
= strna(tpm2_hash_alg_to_string(s
->hash
));
1421 _cleanup_free_
char *mask
= tpm2_pcr_mask_to_string(tpm2_tpms_pcr_selection_to_mask(s
));
1425 return strjoin(algstr
, "(", mask
, ")");
1428 size_t tpm2_tpms_pcr_selection_weight(const TPMS_PCR_SELECTION
*s
) {
1431 return popcount(tpm2_tpms_pcr_selection_to_mask(s
));
1434 /* Utility functions for TPML_PCR_SELECTION. */
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
) {
1439 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1440 assert(index
< l
->count
);
1442 size_t s
= l
->count
- (index
+ 1);
1443 memmove(&l
->pcrSelections
[index
], &l
->pcrSelections
[index
+ 1], s
* sizeof(l
->pcrSelections
[0]));
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
) {
1455 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
1457 TPMS_PCR_SELECTION
*selection
= NULL
;
1458 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s
, l
)
1459 if (s
->hash
== hash_alg
) {
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
];
1474 if (s
->hash
== hash_alg
) {
1475 tpm2_tpms_pcr_selection_move(selection
, s
);
1476 tpm2_tpml_pcr_selection_remove_index(l
, i
);
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
);
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
) {
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
;
1499 TPMS_PCR_SELECTION
*s
;
1500 s
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(&lcopy
, hash_alg
);
1504 return tpm2_tpms_pcr_selection_to_mask(s
);
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
) {
1511 TPMS_PCR_SELECTION s
;
1512 tpm2_tpms_pcr_selection_from_mask(mask
, hash_alg
, &s
);
1514 *ret
= (TPML_PCR_SELECTION
){
1516 .pcrSelections
[0] = s
,
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
) {
1527 if (tpm2_tpms_pcr_selection_is_empty(s
))
1530 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1532 tpm2_tpms_pcr_selection_add(selection
, s
);
1536 /* It's already broken if the count is higher than the array has size for. */
1537 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
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
);
1543 assert(l
->count
< ELEMENTSOF(l
->pcrSelections
));
1544 l
->pcrSelections
[l
->count
++] = *s
;
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
) {
1553 if (tpm2_tpms_pcr_selection_is_empty(s
))
1556 TPMS_PCR_SELECTION
*selection
= tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l
, s
->hash
);
1558 tpm2_tpms_pcr_selection_sub(selection
, s
);
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
) {
1565 return FLAGS_SET(tpm2_tpml_pcr_selection_to_mask(l
, hash
), mask
);
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
;
1574 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1575 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(l
, &tpms
);
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
;
1584 tpm2_tpms_pcr_selection_from_mask(mask
, hash
, &tpms
);
1585 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(l
, &tpms
);
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
) {
1593 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1594 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a
, selection_b
);
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
) {
1602 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b
, b
)
1603 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a
, selection_b
);
1606 char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION
*l
) {
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
))
1614 _cleanup_free_
char *str
= tpm2_tpms_pcr_selection_to_string(s
);
1615 if (!str
|| !strextend_with_separator(&banks
, ",", str
))
1619 return strjoin("[", strempty(banks
), "]");
1622 size_t tpm2_tpml_pcr_selection_weight(const TPML_PCR_SELECTION
*l
) {
1624 assert(l
->count
<= ELEMENTSOF(l
->pcrSelections
));
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
);
1636 bool tpm2_pcr_value_valid(const Tpm2PCRValue
*pcr_value
) {
1642 if (!TPM2_PCR_INDEX_VALID(pcr_value
->index
)) {
1643 log_debug("PCR index %u invalid.", pcr_value
->index
);
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
);
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
);
1663 /* Verify all entries are valid, and consistent with each other. The requirements for consistency are:
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
1668 * Returns true if all entries are valid (or if no entries are provided), false otherwise.
1670 bool tpm2_pcr_values_valid(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
) {
1671 if (!pcr_values
&& n_pcr_values
> 0)
1674 const Tpm2PCRValue
*previous
= NULL
;
1675 FOREACH_ARRAY(current
, pcr_values
, n_pcr_values
) {
1676 if (!tpm2_pcr_value_valid(current
))
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
);
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
);
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
);
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);
1715 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1716 if (v
->value
.size
> 0)
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);
1726 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1727 if (v
->value
.size
== 0)
1733 static int cmp_pcr_values(const Tpm2PCRValue
*a
, const Tpm2PCRValue
*b
) {
1737 return CMP(a
->hash
, b
->hash
) ?: CMP(a
->index
, b
->index
);
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
);
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;
1750 assert(ret_pcr_values
);
1751 assert(ret_n_pcr_values
);
1753 FOREACH_PCR_IN_MASK(index
, mask
)
1754 if (!GREEDY_REALLOC_APPEND(
1757 &TPM2_PCR_VALUE_MAKE(index
, hash
, {}),
1759 return log_oom_debug();
1761 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1762 *ret_n_pcr_values
= n_pcr_values
;
1767 int tpm2_pcr_values_to_mask(const Tpm2PCRValue
*pcr_values
, size_t n_pcr_values
, TPMI_ALG_HASH hash
, uint32_t *ret_mask
) {
1770 assert(pcr_values
|| n_pcr_values
== 0);
1773 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1774 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid PCR values.");
1776 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
1777 if (v
->hash
== hash
)
1778 SET_BIT(mask
, v
->index
);
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
) {
1792 TPML_PCR_SELECTION selection
= {};
1793 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
1794 size_t n_values
= 0;
1796 assert(pcr_values
|| n_pcr_values
== 0);
1798 if (!tpm2_pcr_values_valid(pcr_values
, n_pcr_values
))
1799 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR values are not valid.");
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
));
1804 if (!GREEDY_REALLOC_APPEND(values
, n_values
, &v
->value
, 1))
1805 return log_oom_debug();
1809 *ret_selection
= selection
;
1811 *ret_values
= TAKE_PTR(values
);
1813 *ret_n_values
= n_values
;
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
;
1826 r
= tpm2_tpml_pcr_selection_from_pcr_values(
1830 /* ret_values= */ NULL
,
1831 /* ret_n_values= */ NULL
);
1835 *ret_count
= selection
.count
;
1840 /* Parse a string argument into a Tpm2PCRValue object.
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
;
1851 assert(ret_pcr_value
);
1853 _cleanup_free_
char *index
= NULL
;
1854 r
= extract_first_word(&p
, &index
, ":", /* flags= */ 0);
1856 return log_debug_errno(r
, "Could not parse pcr value '%s': %m", p
);
1858 r
= tpm2_pcr_index_from_string(index
);
1860 return log_debug_errno(r
, "Invalid pcr index '%s': %m", index
);
1861 pcr_value
.index
= (unsigned) r
;
1864 _cleanup_free_
char *hash
= NULL
;
1865 r
= extract_first_word(&p
, &hash
, "=", /* flags= */ 0);
1867 return log_debug_errno(r
, "Could not parse pcr hash algorithm '%s': %m", p
);
1869 r
= tpm2_hash_alg_from_string(hash
);
1871 return log_debug_errno(r
, "Invalid pcr hash algorithm '%s': %m", hash
);
1872 pcr_value
.hash
= (TPMI_ALG_HASH
) r
;
1875 /* Remove leading 0x if present */
1876 p
= startswith_no_case(p
, "0x") ?: p
;
1878 _cleanup_free_
void *buf
= NULL
;
1879 size_t buf_size
= 0;
1880 r
= unhexmem(p
, &buf
, &buf_size
);
1882 return log_debug_errno(r
, "Invalid pcr hash value '%s': %m", p
);
1884 r
= TPM2B_DIGEST_CHECK_SIZE(buf_size
);
1886 return log_debug_errno(r
, "PCR hash value size %zu too large.", buf_size
);
1888 pcr_value
.value
= TPM2B_DIGEST_MAKE(buf
, buf_size
);
1892 *ret_pcr_value
= pcr_value
;
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
;
1903 if (asprintf(&index
, "%u", pcr_value
->index
) < 0)
1906 const char *hash
= pcr_value
->hash
> 0 ? tpm2_hash_alg_to_string(pcr_value
->hash
) : NULL
;
1908 if (hash
&& pcr_value
->value
.size
> 0) {
1909 value
= hexmem(pcr_value
->value
.buffer
, pcr_value
->value
.size
);
1914 return strjoin(index
, hash
? ":" : "", strempty(hash
), value
? "=" : "", strempty(value
));
1917 /* Parse a string argument into an array of Tpm2PCRValue objects.
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
;
1926 assert(ret_pcr_values
);
1927 assert(ret_n_pcr_values
);
1929 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
1930 size_t n_pcr_values
= 0;
1933 _cleanup_free_
char *pcr_arg
= NULL
;
1934 r
= extract_first_word(&p
, &pcr_arg
, ",+", /* flags= */ 0);
1936 return log_debug_errno(r
, "Could not parse pcr values '%s': %m", p
);
1940 Tpm2PCRValue pcr_value
;
1941 r
= tpm2_pcr_value_from_string(pcr_arg
, &pcr_value
);
1945 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
1946 return log_oom_debug();
1949 *ret_pcr_values
= TAKE_PTR(pcr_values
);
1950 *ret_n_pcr_values
= n_pcr_values
;
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
;
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
))
1966 return s
? TAKE_PTR(s
) : strdup("");
1969 void tpm2_log_debug_tpml_pcr_selection(const TPML_PCR_SELECTION
*l
, const char *msg
) {
1970 if (!DEBUG_LOGGING
|| !l
)
1973 _cleanup_free_
char *s
= tpm2_tpml_pcr_selection_to_string(l
);
1974 log_debug("%s: %s", msg
?: "PCR selection", strna(s
));
1977 void tpm2_log_debug_pcr_value(const Tpm2PCRValue
*pcr_value
, const char *msg
) {
1978 if (!DEBUG_LOGGING
|| !pcr_value
)
1981 _cleanup_free_
char *s
= tpm2_pcr_value_to_string(pcr_value
);
1982 log_debug("%s: %s", msg
?: "PCR value", strna(s
));
1985 void tpm2_log_debug_buffer(const void *buffer
, size_t size
, const char *msg
) {
1986 if (!DEBUG_LOGGING
|| !buffer
|| size
== 0)
1989 _cleanup_free_
char *h
= hexmem(buffer
, size
);
1990 log_debug("%s: %s", msg
?: "Buffer", strna(h
));
1993 void tpm2_log_debug_digest(const TPM2B_DIGEST
*digest
, const char *msg
) {
1995 tpm2_log_debug_buffer(digest
->buffer
, digest
->size
, msg
?: "Digest");
1998 void tpm2_log_debug_name(const TPM2B_NAME
*name
, const char *msg
) {
2000 tpm2_log_debug_buffer(name
->name
, name
->size
, msg
?: "Name");
2003 static int tpm2_get_policy_digest(
2005 const Tpm2Handle
*session
,
2006 TPM2B_DIGEST
**ret_policy_digest
) {
2010 if (!DEBUG_LOGGING
&& !ret_policy_digest
)
2016 log_debug("Acquiring policy digest.");
2018 _cleanup_(Esys_Freep
) TPM2B_DIGEST
*policy_digest
= NULL
;
2019 rc
= sym_Esys_PolicyGetDigest(
2021 session
->esys_handle
,
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
));
2030 tpm2_log_debug_digest(policy_digest
, "Session policy digest");
2032 if (ret_policy_digest
)
2033 *ret_policy_digest
= TAKE_PTR(policy_digest
);
2038 int tpm2_create_primary(
2040 const Tpm2Handle
*session
,
2041 const TPM2B_PUBLIC
*template,
2042 const TPM2B_SENSITIVE_CREATE
*sensitive
,
2043 TPM2B_PUBLIC
**ret_public
,
2044 Tpm2Handle
**ret_handle
) {
2053 log_debug("Creating primary key on TPM.");
2055 ts
= now(CLOCK_MONOTONIC
);
2057 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2058 r
= tpm2_handle_new(c
, &handle
);
2062 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2063 rc
= sym_Esys_CreatePrimary(
2066 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2069 sensitive
?: &(TPM2B_SENSITIVE_CREATE
) {},
2071 /* outsideInfo= */ NULL
,
2072 &(TPML_PCR_SELECTION
) {},
2073 &handle
->esys_handle
,
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
));
2083 log_debug("Successfully created primary key on TPM in %s.",
2084 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2087 *ret_public
= TAKE_PTR(public);
2089 *ret_handle
= TAKE_PTR(handle
);
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
) {
2111 log_debug("Creating object on TPM.");
2113 ts
= now(CLOCK_MONOTONIC
);
2115 TPM2B_PUBLIC tpm2b_public
= {
2116 .size
= sizeof(*template) - sizeof(template->unique
),
2117 .publicArea
= *template,
2120 /* Zero the unique area. */
2121 zero(tpm2b_public
.publicArea
.unique
);
2123 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2125 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2126 .size
= sizeof(*sensitive
),
2127 .sensitive
= *sensitive
,
2130 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2132 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2133 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2134 rc
= sym_Esys_Create(
2136 parent
->esys_handle
,
2137 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2142 /* outsideInfo= */ NULL
,
2143 &(TPML_PCR_SELECTION
) {},
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
));
2154 log_debug("Successfully created object on TPM in %s.",
2155 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2158 *ret_public
= TAKE_PTR(public);
2160 *ret_private
= TAKE_PTR(private);
2167 const Tpm2Handle
*parent
,
2168 const Tpm2Handle
*session
,
2169 const TPM2B_PUBLIC
*public,
2170 const TPM2B_PRIVATE
*private,
2171 Tpm2Handle
**ret_handle
) {
2181 log_debug("Loading object into TPM.");
2183 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2184 r
= tpm2_handle_new(c
, &handle
);
2190 parent
? parent
->esys_handle
: ESYS_TR_RH_OWNER
,
2191 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
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
));
2204 *ret_handle
= TAKE_PTR(handle
);
2209 static int tpm2_load_external(
2211 const Tpm2Handle
*session
,
2212 const TPM2B_PUBLIC
*public,
2213 const TPM2B_SENSITIVE
*private,
2214 Tpm2Handle
**ret_handle
) {
2222 log_debug("Loading external key into TPM.");
2224 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2225 r
= tpm2_handle_new(c
, &handle
);
2229 rc
= sym_Esys_LoadExternal(
2231 session
? session
->esys_handle
: ESYS_TR_NONE
,
2237 /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
2238 * hierarchy, older versions need TPM2_RH_* instead. */
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
));
2248 *ret_handle
= TAKE_PTR(handle
);
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(
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
) {
2273 log_debug("Creating loaded object on TPM.");
2275 ts
= now(CLOCK_MONOTONIC
);
2277 /* Copy the input template and zero the unique area. */
2278 TPMT_PUBLIC template_copy
= *template;
2279 zero(template_copy
.unique
);
2281 TPM2B_TEMPLATE tpm2b_template
;
2283 rc
= sym_Tss2_MU_TPMT_PUBLIC_Marshal(
2285 tpm2b_template
.buffer
,
2286 sizeof(tpm2b_template
.buffer
),
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
;
2294 TPM2B_SENSITIVE_CREATE tpm2b_sensitive
;
2296 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {
2297 .size
= sizeof(*sensitive
),
2298 .sensitive
= *sensitive
,
2301 tpm2b_sensitive
= (TPM2B_SENSITIVE_CREATE
) {};
2303 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2304 r
= tpm2_handle_new(c
, &handle
);
2308 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*public = NULL
;
2309 _cleanup_(Esys_Freep
) TPM2B_PRIVATE
*private = NULL
;
2310 rc
= sym_Esys_CreateLoaded(
2312 parent
->esys_handle
,
2313 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2318 &handle
->esys_handle
,
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
));
2326 log_debug("Successfully created loaded object on TPM in %s.",
2327 FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - ts
, USEC_PER_MSEC
));
2330 *ret_public
= TAKE_PTR(public);
2332 *ret_private
= TAKE_PTR(private);
2334 *ret_handle
= TAKE_PTR(handle
);
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(
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
) {
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
);
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);
2365 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
2366 r
= tpm2_load(c
, parent
, session
, public, private, &handle
);
2371 *ret_public
= TAKE_PTR(public);
2373 *ret_private
= TAKE_PTR(private);
2375 *ret_handle
= TAKE_PTR(handle
);
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
;
2389 blob
= malloc0(max_size
);
2391 return log_oom_debug();
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
));
2398 *ret
= TAKE_PTR(blob
);
2399 *ret_size
= blob_size
;
2403 static int tpm2_unmarshal_private(const void *data
, size_t size
, TPM2B_PRIVATE
*ret_private
) {
2404 TPM2B_PRIVATE
private = {};
2408 assert(data
|| size
== 0);
2409 assert(ret_private
);
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
));
2416 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2417 "Garbage at end of private key marshal data.");
2419 *ret_private
= private;
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
;
2432 blob
= malloc0(max_size
);
2434 return log_oom_debug();
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
));
2441 *ret
= TAKE_PTR(blob
);
2442 *ret_size
= blob_size
;
2446 static int tpm2_unmarshal_public(const void *data
, size_t size
, TPM2B_PUBLIC
*ret_public
) {
2447 TPM2B_PUBLIC
public = {};
2451 assert(data
|| size
== 0);
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
));
2459 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2460 "Garbage at end of public key marshal data.");
2462 *ret_public
= public;
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
;
2475 blob
= malloc0(max_size
);
2477 return log_oom_debug();
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
));
2484 *ret
= TAKE_PTR(blob
);
2485 *ret_size
= blob_size
;
2489 int tpm2_unmarshal_nv_public(const void *data
, size_t size
, TPM2B_NV_PUBLIC
*ret_nv_public
) {
2490 TPM2B_NV_PUBLIC nv_public
= {};
2494 assert(data
|| size
== 0);
2495 assert(ret_nv_public
);
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
));
2502 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2503 "Garbage at end of NV public structure marshal data.");
2505 *ret_nv_public
= nv_public
;
2509 static int tpm2_import(
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
) {
2524 assert(!!encryption_key
== !!symmetric
);
2528 assert(ret_private
);
2530 log_debug("Importing key into TPM.");
2532 rc
= sym_Esys_Import(
2534 parent
->esys_handle
,
2535 session
? session
->esys_handle
: ESYS_TR_PASSWORD
,
2542 symmetric
?: &(TPMT_SYM_DEF_OBJECT
){ .algorithm
= TPM2_ALG_NULL
, },
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
));
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
2558 const TPML_PCR_SELECTION
*pcr_selection
,
2559 Tpm2PCRValue
**ret_pcr_values
,
2560 size_t *ret_n_pcr_values
) {
2562 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
2563 size_t n_pcr_values
= 0;
2567 assert(pcr_selection
);
2568 assert(ret_pcr_values
);
2569 assert(ret_n_pcr_values
);
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
;
2576 tpm2_log_debug_tpml_pcr_selection(&remaining
, "Reading PCR selection");
2578 /* Unfortunately, PCR_Read will not return more than 8 values. */
2579 rc
= sym_Esys_PCR_Read(
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
));
2592 tpm2_log_debug_tpml_pcr_selection(current_read
, "Read PCR selection");
2594 if (tpm2_tpml_pcr_selection_is_empty(current_read
)) {
2595 log_debug("TPM2 refused to read possibly unimplemented PCRs, ignoring.");
2600 FOREACH_PCR_IN_TPML_PCR_SELECTION(index
, tpms
, current_read
) {
2601 assert(i
< current_values
->count
);
2602 Tpm2PCRValue pcr_value
= {
2605 .value
= current_values
->digests
[i
++],
2608 tpm2_log_debug_pcr_value(&pcr_value
, /* msg= */ NULL
);
2610 if (!GREEDY_REALLOC_APPEND(pcr_values
, n_pcr_values
, &pcr_value
, 1))
2611 return log_oom_debug();
2613 assert(i
== current_values
->count
);
2615 tpm2_tpml_pcr_selection_sub(&remaining
, current_read
);
2618 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
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.");
2623 *ret_pcr_values
= TAKE_PTR(pcr_values
);
2624 *ret_n_pcr_values
= n_pcr_values
;
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;
2638 assert(pcr_values
|| n_pcr_values
== 0);
2640 if (n_pcr_values
> 0) {
2642 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
2644 return log_debug_errno(r
, "Could not get hash count from pcr values: %m");
2646 if (hash_count
== 1 && pcr_values
[0].hash
== 0) {
2648 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, 0, &mask
);
2652 r
= tpm2_get_best_pcr_bank(c
, mask
, &pcr_bank
);
2658 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
) {
2662 if (v
->value
.size
> 0)
2665 TPML_PCR_SELECTION selection
;
2666 r
= tpm2_tpml_pcr_selection_from_pcr_values(v
, 1, &selection
, NULL
, NULL
);
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
);
2676 if (n_read_values
== 0)
2677 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
2678 "Could not read PCR hash 0x%" PRIu16
" index %u",
2681 assert(n_read_values
== 1);
2682 assert(read_values
[0].hash
== v
->hash
);
2683 assert(read_values
[0].index
== v
->index
);
2685 v
->value
= read_values
[0].value
;
2691 static int tpm2_pcr_mask_good(
2696 TPML_PCR_SELECTION selection
;
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. */
2705 tpm2_tpml_pcr_selection_from_mask(mask
, bank
, &selection
);
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
);
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
))
2722 static int tpm2_bank_has24(const TPMS_PCR_SELECTION
*selection
) {
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
)));
2734 assert_cc(TPM2_PCRS_MAX
% 8 == 0);
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. */
2739 for (size_t j
= 0; j
< TPM2_PCRS_MAX
/8; j
++)
2740 if (selection
->pcrSelect
[j
] != 0xFF) {
2746 log_debug("TPM2 PCR bank %s has fewer than 24 PCR bits enabled, ignoring.",
2747 strna(tpm2_hash_alg_to_string(selection
->hash
)));
2752 int tpm2_get_best_pcr_bank(
2755 TPMI_ALG_HASH
*ret
) {
2757 TPMI_ALG_HASH supported_hash
= 0, hash_with_valid_pcr
= 0;
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... */
2769 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2770 TPMI_ALG_HASH hash
= selection
->hash
;
2773 /* For now we are only interested in the SHA1 and SHA256 banks */
2774 if (!IN_SET(hash
, TPM2_ALG_SHA256
, TPM2_ALG_SHA1
))
2777 r
= tpm2_bank_has24(selection
);
2783 good
= tpm2_pcr_mask_good(c
, hash
, pcr_mask
);
2787 if (hash
== TPM2_ALG_SHA256
) {
2788 supported_hash
= TPM2_ALG_SHA256
;
2790 /* Great, SHA256 is supported and has initialized PCR values, we are done. */
2791 hash_with_valid_pcr
= TPM2_ALG_SHA256
;
2795 assert(hash
== TPM2_ALG_SHA1
);
2797 if (supported_hash
== 0)
2798 supported_hash
= TPM2_ALG_SHA1
;
2800 if (good
&& hash_with_valid_pcr
== 0)
2801 hash_with_valid_pcr
= TPM2_ALG_SHA1
;
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
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. */
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.");
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.");
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
;
2832 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2833 "TPM2 module supports neither SHA1 nor SHA256 PCR banks, cannot operate.");
2838 int tpm2_get_good_pcr_banks(
2841 TPMI_ALG_HASH
**ret
) {
2843 _cleanup_free_ TPMI_ALG_HASH
*good_banks
= NULL
, *fallback_banks
= NULL
;
2844 size_t n_good_banks
= 0, n_fallback_banks
= 0;
2850 FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection
, &c
->capability_pcrs
) {
2851 TPMI_ALG_HASH hash
= selection
->hash
;
2853 /* Let's see if this bank is superficially OK, i.e. has at least 24 enabled registers */
2854 r
= tpm2_bank_has24(selection
);
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
);
2865 if (n_good_banks
+ n_fallback_banks
>= INT_MAX
)
2866 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many good TPM2 banks?");
2869 if (!GREEDY_REALLOC(good_banks
, n_good_banks
+1))
2870 return log_oom_debug();
2872 good_banks
[n_good_banks
++] = hash
;
2874 if (!GREEDY_REALLOC(fallback_banks
, n_fallback_banks
+1))
2875 return log_oom_debug();
2877 fallback_banks
[n_fallback_banks
++] = hash
;
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
;
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
;
2894 /* No suitable banks found. */
2899 int tpm2_get_good_pcr_banks_strv(
2905 _cleanup_free_ TPMI_ALG_HASH
*algs
= NULL
;
2906 _cleanup_strv_free_
char **l
= NULL
;
2912 n_algs
= tpm2_get_good_pcr_banks(c
, pcr_mask
, &algs
);
2916 FOREACH_ARRAY(a
, algs
, n_algs
) {
2917 _cleanup_free_
char *n
= NULL
;
2918 const EVP_MD
*implementation
;
2921 salg
= tpm2_hash_alg_to_string(*a
);
2923 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "TPM2 operates with unknown PCR algorithm, can't measure.");
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.");
2929 n
= strdup(ASSERT_PTR(EVP_MD_name(implementation
)));
2931 return log_oom_debug();
2933 ascii_strlower(n
); /* OpenSSL uses uppercase digest names, we prefer them lower case. */
2935 if (strv_consume(&l
, TAKE_PTR(n
)) < 0)
2936 return log_oom_debug();
2941 #else /* HAVE_OPENSSL */
2942 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
2946 /* Hash data into the digest.
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.
2953 * On success, the digest hash will be updated with the hashing operation result and the digest size will be
2954 * correct for 'alg'.
2956 * This currently only provides SHA256, so 'alg' must be TPM2_ALG_SHA256. */
2957 int tpm2_digest_many(
2959 TPM2B_DIGEST
*digest
,
2960 const struct iovec data
[],
2964 struct sha256_ctx ctx
;
2967 assert(data
|| n_data
== 0);
2969 if (alg
!= TPM2_ALG_SHA256
)
2970 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
2971 "Hash algorithm not supported: 0x%x", alg
);
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
);
2978 /* Since we're hardcoding SHA256 (for now), we can check this at compile time. */
2979 assert_cc(sizeof(digest
->buffer
) >= SHA256_DIGEST_SIZE
);
2983 sha256_init_ctx(&ctx
);
2986 sha256_process_bytes(digest
->buffer
, digest
->size
, &ctx
);
2988 *digest
= (TPM2B_DIGEST
) {
2989 .size
= SHA256_DIGEST_SIZE
,
2991 if (n_data
== 0) /* If not extending and no data, return zero hash */
2995 FOREACH_ARRAY(d
, data
, n_data
)
2996 sha256_process_bytes(d
->iov_base
, d
->iov_len
, &ctx
);
2998 sha256_finish_ctx(&ctx
, digest
->buffer
);
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(
3006 TPM2B_DIGEST
*digest
,
3007 const TPM2B_DIGEST data
[],
3011 _cleanup_free_
struct iovec
*iovecs
= NULL
;
3013 assert(data
|| n_data
== 0);
3015 iovecs
= new(struct iovec
, n_data
);
3017 return log_oom_debug();
3019 for (size_t i
= 0; i
< n_data
; i
++)
3020 iovecs
[i
] = IOVEC_MAKE((void*) data
[i
].buffer
, data
[i
].size
);
3022 return tpm2_digest_many(alg
, digest
, iovecs
, n_data
, extend
);
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.
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.
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
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.
3045 static void tpm2_trim_auth_value(TPM2B_AUTH
*auth
) {
3046 bool trimmed
= false;
3050 while (auth
->size
> 0 && auth
->buffer
[auth
->size
- 1] == 0) {
3056 log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
3059 int tpm2_get_pin_auth(TPMI_ALG_HASH hash
, const char *pin
, TPM2B_AUTH
*ret_auth
) {
3060 TPM2B_AUTH auth
= {};
3066 r
= tpm2_digest_buffer(hash
, &auth
, pin
, strlen(pin
), /* extend= */ false);
3070 tpm2_trim_auth_value(&auth
);
3072 *ret_auth
= TAKE_STRUCT(auth
);
3077 int tpm2_set_auth_binary(Tpm2Context
*c
, const Tpm2Handle
*handle
, const TPM2B_AUTH
*auth
) {
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
));
3094 int tpm2_set_auth(Tpm2Context
*c
, const Tpm2Handle
*handle
, const char *pin
) {
3095 TPM2B_AUTH auth
= {};
3104 CLEANUP_ERASE(auth
);
3106 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &auth
);
3110 return tpm2_set_auth_binary(c
, handle
, &auth
);
3113 static bool tpm2_is_encryption_session(Tpm2Context
*c
, const Tpm2Handle
*session
) {
3114 TPMA_SESSION flags
= 0;
3120 rc
= sym_Esys_TRSess_GetAttributes(c
->esys_context
, session
->esys_handle
, &flags
);
3121 if (rc
!= TSS2_RC_SUCCESS
)
3124 return (flags
& TPMA_SESSION_DECRYPT
) && (flags
& TPMA_SESSION_ENCRYPT
);
3127 int tpm2_make_encryption_session(
3129 const Tpm2Handle
*primary
,
3130 const Tpm2Handle
*bind_key
,
3131 Tpm2Handle
**ret_session
) {
3133 const TPMA_SESSION sessionAttributes
= TPMA_SESSION_DECRYPT
| TPMA_SESSION_ENCRYPT
|
3134 TPMA_SESSION_CONTINUESESSION
;
3140 assert(ret_session
);
3142 log_debug("Starting HMAC encryption session.");
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
);
3152 rc
= sym_Esys_StartAuthSession(
3154 primary
->esys_handle
,
3155 bind_key
? bind_key
->esys_handle
: ESYS_TR_NONE
,
3161 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
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
));
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
));
3176 *ret_session
= TAKE_PTR(session
);
3181 int tpm2_make_policy_session(
3183 const Tpm2Handle
*primary
,
3184 const Tpm2Handle
*encryption_session
,
3185 Tpm2Handle
**ret_session
) {
3192 assert(encryption_session
);
3193 assert(ret_session
);
3195 if (!tpm2_is_encryption_session(c
, encryption_session
))
3196 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
3197 "Missing encryption session");
3199 log_debug("Starting policy session.");
3201 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*session
= NULL
;
3202 r
= tpm2_handle_new(c
, &session
);
3206 rc
= sym_Esys_StartAuthSession(
3208 primary
->esys_handle
,
3210 encryption_session
->esys_handle
,
3215 &SESSION_TEMPLATE_SYM_AES_128_CFB
,
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
));
3222 *ret_session
= TAKE_PTR(session
);
3227 static int find_signature(
3229 const TPML_PCR_SELECTION
*pcr_selection
,
3234 void *ret_signature
,
3235 size_t *ret_signature_size
) {
3242 /* Searches for a signature blob in the specified JSON object. Search keys are PCR bank, PCR mask,
3243 * public key, and policy digest. */
3245 if (!json_variant_is_object(v
))
3246 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Signature is not a JSON object.");
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
);
3251 k
= tpm2_hash_alg_to_string(pcr_bank
);
3253 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Don't know PCR bank %" PRIu16
, pcr_bank
);
3255 /* First, find field by bank */
3256 b
= json_variant_by_key(v
, k
);
3258 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
), "Signature lacks data for PCR bank '%s'.", k
);
3260 if (!json_variant_is_array(b
))
3261 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data is not a JSON array.");
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
;
3270 if (!json_variant_is_object(i
))
3271 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Bank data element is not a JSON object");
3273 /* Check if the PCR mask matches our expectations */
3274 maskj
= json_variant_by_key(i
, "pcrs");
3278 r
= tpm2_parse_pcr_json_array(maskj
, &parsed_mask
);
3280 return log_debug_errno(r
, "Failed to parse JSON PCR mask");
3282 if (parsed_mask
!= pcr_mask
)
3283 continue; /* Not for this PCR mask */
3285 /* Then check if this is for the public key we operate with */
3286 fpj
= json_variant_by_key(i
, "pkfp");
3290 r
= json_variant_unhex(fpj
, &fpj_data
, &fpj_size
);
3292 return log_debug_errno(r
, "Failed to decode fingerprint in JSON data: %m");
3294 if (memcmp_nn(fp
, fp_size
, fpj_data
, fpj_size
) != 0)
3295 continue; /* Not for this public key */
3297 /* Finally, check if this is for the PCR policy we expect this to be */
3298 polj
= json_variant_by_key(i
, "pol");
3302 r
= json_variant_unhex(polj
, &polj_data
, &polj_size
);
3304 return log_debug_errno(r
, "Failed to decode policy hash JSON data: %m");
3306 if (memcmp_nn(policy
, policy_size
, polj_data
, polj_size
) != 0)
3309 /* This entry matches all our expectations, now return the signature included in it */
3310 sigj
= json_variant_by_key(i
, "sig");
3314 return json_variant_unbase64(sigj
, ret_signature
, ret_signature_size
);
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.");
3323 /* Calculates the "name" of a public key.
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.
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
) {
3342 return log_debug_errno(r
, "TPM2 support not installed: %m");
3344 if (public->nameAlg
!= TPM2_ALG_SHA256
)
3345 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3346 "Unsupported nameAlg: 0x%x",
3349 _cleanup_free_
uint8_t *buf
= NULL
;
3352 buf
= (uint8_t*) new(TPMT_PUBLIC
, 1);
3354 return log_oom_debug();
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
));
3361 TPM2B_DIGEST digest
= {};
3362 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3367 .hashAlg
= TPM2_ALG_SHA256
,
3369 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3370 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
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
));
3380 tpm2_log_debug_name(&name
, "Calculated public key name");
3387 /* Get the "name" of a key from the TPM.
3389 * The "name" of a key is explained above in tpm2_calculate_pubkey_name().
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(
3395 const Tpm2Handle
*handle
,
3396 TPM2B_NAME
**ret_name
) {
3398 _cleanup_(Esys_Freep
) TPM2B_NAME
*name
= NULL
;
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
));
3410 tpm2_log_debug_name(name
, "Object name");
3412 *ret_name
= TAKE_PTR(name
);
3417 int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC
*nvpublic
, TPM2B_NAME
*ret_name
) {
3426 return log_debug_errno(r
, "TPM2 support not installed: %m");
3428 if (nvpublic
->nameAlg
!= TPM2_ALG_SHA256
)
3429 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
3430 "Unsupported nameAlg: 0x%x",
3433 _cleanup_free_
uint8_t *buf
= NULL
;
3436 buf
= (uint8_t*) new(TPMS_NV_PUBLIC
, 1);
3438 return log_oom_debug();
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
));
3445 TPM2B_DIGEST digest
= {};
3446 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, &digest
, buf
, size
, /* extend= */ false);
3451 .hashAlg
= TPM2_ALG_SHA256
,
3453 assert(digest
.size
<= sizeof(ha
.digest
.sha256
));
3454 memcpy_safe(ha
.digest
.sha256
, digest
.buffer
, digest
.size
);
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
));
3464 tpm2_log_debug_name(&name
, "Calculated NV index name");
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
;
3478 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3482 return log_debug_errno(r
, "TPM2 support not installed: %m");
3484 uint8_t buf
[sizeof(command
)];
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
));
3492 if (offset
!= sizeof(command
))
3493 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3494 "Offset 0x%zx wrong after marshalling PolicyAuthValue command", offset
);
3496 r
= tpm2_digest_buffer(TPM2_ALG_SHA256
, digest
, buf
, offset
, /* extend= */ true);
3500 tpm2_log_debug_digest(digest
, "PolicyAuthValue calculated digest");
3505 int tpm2_policy_auth_value(
3507 const Tpm2Handle
*session
,
3508 TPM2B_DIGEST
**ret_policy_digest
) {
3515 log_debug("Submitting AuthValue policy.");
3517 rc
= sym_Esys_PolicyAuthValue(
3519 session
->esys_handle
,
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
));
3528 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
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
;
3538 assert(public_info
);
3540 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3544 return log_debug_errno(r
, "TPM2 support not installed: %m");
3546 uint8_t buf
[sizeof(command
)];
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
));
3554 if (offset
!= sizeof(command
))
3555 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3556 "Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset
);
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
;
3561 TPM2B_NAME name
= {};
3562 r
= tpm2_calculate_nv_index_name(&public_info_copy
.nvPublic
, &name
);
3566 struct iovec data
[] = {
3567 IOVEC_MAKE(buf
, offset
),
3568 IOVEC_MAKE(name
.name
, name
.size
),
3571 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3575 tpm2_log_debug_digest(digest
, "PolicyAuthorizeNV calculated digest");
3580 int tpm2_policy_authorize_nv(
3582 const Tpm2Handle
*session
,
3583 const Tpm2Handle
*nv_handle
,
3584 TPM2B_DIGEST
**ret_policy_digest
) {
3591 log_debug("Submitting AuthorizeNV policy.");
3593 rc
= sym_Esys_PolicyAuthorizeNV(
3596 nv_handle
->esys_handle
,
3597 session
->esys_handle
,
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
));
3606 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
3611 const Tpm2Handle
*session
,
3612 const TPM2B_DIGEST
*branches
, size_t n_branches
,
3613 TPM2B_DIGEST
**ret_policy_digest
) {
3615 TPML_DIGEST hash_list
;
3621 if (n_branches
> ELEMENTSOF(hash_list
.digests
))
3624 log_debug("Submitting OR policy.");
3626 hash_list
= (TPML_DIGEST
) {
3627 .count
= n_branches
,
3630 memcpy(hash_list
.digests
, branches
, n_branches
* sizeof(TPM2B_DIGEST
));
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
);
3638 rc
= sym_Esys_PolicyOR(
3640 session
->esys_handle
,
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
));
3650 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
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
;
3660 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3662 if (n_branches
== 0)
3664 if (n_branches
== 1)
3665 log_warning("PolicyOR with a single branch submitted, this is weird.");
3671 return log_error_errno(r
, "TPM2 support not installed: %m");
3673 uint8_t buf
[sizeof(command
)];
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
));
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
);
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
);
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
);
3698 /* PolicyOR does not use the previous hash value; we must zero and then extend it. */
3699 zero(digest
->buffer
);
3701 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, 1 + n_branches
, /* extend= */ true);
3705 tpm2_log_debug_digest(digest
, "PolicyOR calculated digest");
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
) {
3716 TPM2_CC command
= TPM2_CC_PolicyPCR
;
3720 assert(pcr_values
|| n_pcr_values
== 0);
3722 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3726 return log_debug_errno(r
, "TPM2 support not installed: %m");
3728 TPML_PCR_SELECTION pcr_selection
;
3729 _cleanup_free_ TPM2B_DIGEST
*values
= NULL
;
3731 r
= tpm2_tpml_pcr_selection_from_pcr_values(pcr_values
, n_pcr_values
, &pcr_selection
, &values
, &n_values
);
3733 return log_debug_errno(r
, "Could not convert PCR values to TPML_PCR_SELECTION: %m");
3735 TPM2B_DIGEST hash
= {};
3736 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, &hash
, values
, n_values
, /* extend= */ false);
3740 _cleanup_free_
uint8_t *buf
= NULL
;
3741 size_t size
= 0, maxsize
= sizeof(command
) + sizeof(pcr_selection
);
3743 buf
= malloc(maxsize
);
3745 return log_oom_debug();
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
));
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
));
3757 struct iovec data
[] = {
3758 IOVEC_MAKE(buf
, size
),
3759 IOVEC_MAKE(hash
.buffer
, hash
.size
),
3761 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3765 tpm2_log_debug_digest(digest
, "PolicyPCR calculated digest");
3770 int tpm2_policy_pcr(
3772 const Tpm2Handle
*session
,
3773 const TPML_PCR_SELECTION
*pcr_selection
,
3774 TPM2B_DIGEST
**ret_policy_digest
) {
3780 assert(pcr_selection
);
3782 log_debug("Submitting PCR hash policy.");
3784 rc
= sym_Esys_PolicyPCR(
3786 session
->esys_handle
,
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
));
3796 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
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
) {
3805 TPM2_CC command
= TPM2_CC_PolicyAuthorize
;
3811 assert(digest
->size
== SHA256_DIGEST_SIZE
);
3815 return log_debug_errno(r
, "TPM2 support not installed: %m");
3817 uint8_t buf
[sizeof(command
)];
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
));
3825 if (offset
!= sizeof(command
))
3826 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
3827 "Offset 0x%zx wrong after marshalling PolicyAuthorize command", offset
);
3829 TPM2B_NAME name
= {};
3830 r
= tpm2_calculate_pubkey_name(&public->publicArea
, &name
);
3834 /* PolicyAuthorize does not use the previous hash value; we must zero and then extend it. */
3835 zero(digest
->buffer
);
3837 struct iovec data
[] = {
3838 IOVEC_MAKE(buf
, offset
),
3839 IOVEC_MAKE(name
.name
, name
.size
),
3841 r
= tpm2_digest_many(TPM2_ALG_SHA256
, digest
, data
, ELEMENTSOF(data
), /* extend= */ true);
3845 /* PolicyAuthorize requires hashing twice; this is either an extension or rehashing. */
3847 r
= tpm2_digest_many_digests(TPM2_ALG_SHA256
, digest
, policy_ref
, 1, /* extend= */ true);
3849 r
= tpm2_digest_rehash(TPM2_ALG_SHA256
, digest
);
3853 tpm2_log_debug_digest(digest
, "PolicyAuthorize calculated digest");
3858 static int tpm2_policy_authorize(
3860 const Tpm2Handle
*session
,
3861 TPML_PCR_SELECTION
*pcr_selection
,
3862 const TPM2B_PUBLIC
*public,
3865 JsonVariant
*signature_json
,
3866 TPM2B_DIGEST
**ret_policy_digest
) {
3873 assert(pcr_selection
);
3875 assert(fp
&& fp_size
> 0);
3877 log_debug("Adding PCR signature policy.");
3879 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*pubkey_handle
= NULL
;
3880 r
= tpm2_load_external(c
, NULL
, public, NULL
, &pubkey_handle
);
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
);
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(
3903 _cleanup_free_
void *signature_raw
= NULL
;
3904 size_t signature_size
;
3910 approved_policy
->buffer
,
3911 approved_policy
->size
,
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
);
3924 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size
);
3926 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
), "Signature larger than buffer.");
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
),
3936 rc
= sym_Esys_VerifySignature(
3938 pubkey_handle
->esys_handle
,
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
));
3949 check_ticket
= check_ticket_buffer
;
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
,
3957 check_ticket
= &check_ticket_null
;
3960 rc
= sym_Esys_PolicyAuthorize(
3962 session
->esys_handle
,
3967 /* policyRef= */ &(const TPM2B_NONCE
) {},
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
));
3974 return tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
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,
3983 const Tpm2PCRLockPolicy
*pcrlock_policy
,
3984 TPM2B_DIGEST
*digest
) {
3988 assert(pcr_values
|| n_pcr_values
== 0);
3991 if (public && pcrlock_policy
)
3992 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Policies with both signed PCR and pcrlock are currently not supported.");
3995 r
= tpm2_calculate_policy_authorize(public, NULL
, digest
);
4000 if (pcrlock_policy
) {
4001 TPM2B_NV_PUBLIC nv_public
;
4003 r
= tpm2_unmarshal_nv_public(
4004 pcrlock_policy
->nv_public
.iov_base
,
4005 pcrlock_policy
->nv_public
.iov_len
,
4010 r
= tpm2_calculate_policy_authorize_nv(&nv_public
, digest
);
4015 if (n_pcr_values
> 0) {
4016 r
= tpm2_calculate_policy_pcr(pcr_values
, n_pcr_values
, digest
);
4022 r
= tpm2_calculate_policy_auth_value(digest
);
4030 static int tpm2_build_sealing_policy(
4032 const Tpm2Handle
*session
,
4033 uint32_t hash_pcr_mask
,
4035 const TPM2B_PUBLIC
*public,
4038 uint32_t pubkey_pcr_mask
,
4039 JsonVariant
*signature_json
,
4041 const Tpm2PCRLockPolicy
*pcrlock_policy
,
4042 TPM2B_DIGEST
**ret_policy_digest
) {
4048 assert(pubkey_pcr_mask
== 0 || public);
4050 log_debug("Building sealing policy.");
4052 if ((hash_pcr_mask
| pubkey_pcr_mask
) != 0) {
4053 r
= tpm2_pcr_mask_good(c
, pcr_bank
, hash_pcr_mask
|pubkey_pcr_mask
);
4057 log_debug("Selected TPM2 PCRs are not initialized on this system.");
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.");
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
);
4071 if (pcrlock_policy
) {
4072 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*nv_handle
= NULL
;
4074 r
= tpm2_policy_super_pcr(
4077 &pcrlock_policy
->prediction
,
4078 pcrlock_policy
->algorithm
);
4082 r
= tpm2_deserialize(
4084 pcrlock_policy
->nv_handle
.iov_base
,
4085 pcrlock_policy
->nv_handle
.iov_len
,
4090 r
= tpm2_policy_authorize_nv(
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
);
4108 r
= tpm2_policy_auth_value(c
, session
, NULL
);
4113 r
= tpm2_get_policy_digest(c
, session
, ret_policy_digest
);
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
, },
4133 static int tpm2_ecc_curve_from_openssl_curve_id(int openssl_ecc_curve_id
, TPM2_ECC_CURVE
*ret
) {
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
;
4142 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4143 "OpenSSL ECC curve id %d not supported.", openssl_ecc_curve_id
);
4146 static int tpm2_ecc_curve_to_openssl_curve_id(TPM2_ECC_CURVE tpm2_ecc_curve_id
, int *ret
) {
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
;
4155 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4156 "TPM2 ECC curve %u not supported.", tpm2_ecc_curve_id
);
4159 #define TPM2_RSA_DEFAULT_EXPONENT UINT32_C(0x10001)
4161 int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC
*public, EVP_PKEY
**ret
) {
4167 const TPMT_PUBLIC
*p
= &public->publicArea
;
4169 case TPM2_ALG_ECC
: {
4171 r
= tpm2_ecc_curve_to_openssl_curve_id(p
->parameters
.eccDetail
.curveID
, &curve_id
);
4175 const TPMS_ECC_POINT
*point
= &p
->unique
.ecc
;
4176 return ecc_pkey_from_curve_x_y(
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
,
4196 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4197 "TPM2 asymmetric algorithm 0x%" PRIx16
" not supported.", p
->type
);
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
) {
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
,
4221 #if OPENSSL_VERSION_MAJOR >= 3
4222 key_id
= EVP_PKEY_get_id(pkey
);
4224 key_id
= EVP_PKEY_id(pkey
);
4229 public.type
= TPM2_ALG_ECC
;
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
);
4236 return log_debug_errno(r
, "Could not get ECC key curve/x/y: %m");
4238 TPM2_ECC_CURVE curve
;
4239 r
= tpm2_ecc_curve_from_openssl_curve_id(curve_id
, &curve
);
4243 public.parameters
.eccDetail
.curveID
= curve
;
4245 public.parameters
.eccDetail
.kdf
.scheme
= TPM2_ALG_NULL
;
4247 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
4249 return log_debug_errno(r
, "ECC key x size %zu too large.", x_size
);
4251 public.unique
.ecc
.x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
);
4253 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
4255 return log_debug_errno(r
, "ECC key y size %zu too large.", y_size
);
4257 public.unique
.ecc
.y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
);
4261 case EVP_PKEY_RSA
: {
4262 public.type
= TPM2_ALG_RSA
;
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
);
4268 return log_debug_errno(r
, "Could not get RSA key n/e: %m");
4270 r
= TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(n_size
);
4272 return log_debug_errno(r
, "RSA key n size %zu too large.", n_size
);
4274 public.unique
.rsa
= TPM2B_PUBLIC_KEY_RSA_MAKE(n
, n_size
);
4275 public.parameters
.rsaDetail
.keyBits
= n_size
* 8;
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
);
4281 uint32_t exponent
= 0;
4282 memcpy(&exponent
, e
, e_size
);
4283 exponent
= be32toh(exponent
) >> (32 - e_size
* 8);
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
;
4294 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
4295 "EVP_PKEY type %d not supported.", key_id
);
4298 *ret
= (TPM2B_PUBLIC
) {
4299 .size
= sizeof(public),
4300 .publicArea
= public,
4307 int tpm2_tpm2b_public_to_fingerprint(
4308 const TPM2B_PUBLIC
*public,
4309 void **ret_fingerprint
,
4310 size_t *ret_fingerprint_size
) {
4316 assert(ret_fingerprint
);
4317 assert(ret_fingerprint_size
);
4319 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4320 r
= tpm2_tpm2b_public_to_openssl_pkey(public, &pkey
);
4324 /* Hardcode fingerprint to SHA256 */
4325 return pubkey_fingerprint(pkey
, EVP_sha256(), ret_fingerprint
, ret_fingerprint_size
);
4327 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
4331 int tpm2_tpm2b_public_from_pem(const void *pem
, size_t pem_size
, TPM2B_PUBLIC
*ret
) {
4338 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4339 r
= openssl_pkey_from_pem(pem
, pem_size
, &pkey
);
4343 return tpm2_tpm2b_public_from_openssl_pkey(pkey
, ret
);
4345 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
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
,
4358 size_t *ret_blob_size
) {
4365 assert(ret_blob_size
);
4367 size_t max_size
= sizeof(*private) + sizeof(*public);
4369 max_size
+= sizeof(*seed
);
4371 _cleanup_free_
void *blob
= malloc(max_size
);
4373 return log_oom_debug();
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
));
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
));
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
));
4393 *ret_blob
= TAKE_PTR(blob
);
4394 *ret_blob_size
= blob_size
;
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(
4406 TPM2B_PUBLIC
*ret_public
,
4407 TPM2B_PRIVATE
*ret_private
,
4408 TPM2B_ENCRYPTED_SECRET
*ret_seed
) {
4414 assert(ret_private
);
4417 TPM2B_PRIVATE
private = {};
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
));
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
));
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
));
4438 *ret_public
= public;
4439 *ret_private
= private;
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(
4450 const TPM2B_NAME
*name
,
4451 const TPM2B_PUBLIC
*public,
4452 void **ret_serialized
,
4453 size_t *ret_serialized_size
) {
4459 assert(ret_serialized
);
4460 assert(ret_serialized_size
);
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
);
4465 return log_oom_debug();
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
));
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
));
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
));
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
));
4489 *ret_serialized
= TAKE_PTR(serialized
);
4490 *ret_serialized_size
= serialized_size
;
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). */
4499 const Tpm2Handle
*handle
,
4500 void **ret_serialized
,
4501 size_t *ret_serialized_size
) {
4507 assert(ret_serialized
);
4508 assert(ret_serialized_size
);
4510 _cleanup_(Esys_Freep
) unsigned char *serialized
= NULL
;
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
));
4517 *ret_serialized
= TAKE_PTR(serialized
);
4518 *ret_serialized_size
= size
;
4523 int tpm2_deserialize(
4525 const void *serialized
,
4526 size_t serialized_size
,
4527 Tpm2Handle
**ret_handle
) {
4536 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*handle
= NULL
;
4537 r
= tpm2_handle_new(c
, &handle
);
4541 /* Since this is an existing handle in the TPM we should not implicitly flush it. */
4542 handle
->flush
= false;
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
));
4549 *ret_handle
= TAKE_PTR(handle
);
4556 /* KDFa() as defined by the TPM spec. */
4557 static int tpm2_kdfa(
4558 TPMI_ALG_HASH hash_alg
,
4562 const void *context
,
4566 size_t *ret_key_len
) {
4572 assert(context
|| context_len
== 0);
4574 assert(bits
<= SIZE_MAX
- 7);
4576 assert(ret_key_len
);
4578 log_debug("Calculating KDFa().");
4580 size_t len
= DIV_ROUND_UP(bits
, 8);
4582 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4586 _cleanup_free_
void *buf
= NULL
;
4587 r
= kdf_kb_hmac_derive(
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():
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;
4613 ((uint8_t*) buf
)[0] &= 0xffu
>> (8 - partial
);
4615 *ret_key
= TAKE_PTR(buf
);
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
,
4627 const void *context_u
,
4628 size_t context_u_size
,
4629 const void *context_v
,
4630 size_t context_v_size
,
4633 size_t *ret_key_len
) {
4637 assert(shared_secret
);
4642 assert(bits
<= SIZE_MAX
- 7);
4644 assert(ret_key_len
);
4646 log_debug("Calculating KDFe().");
4648 size_t len
= DIV_ROUND_UP(bits
, 8);
4650 const char *hash_alg_name
= tpm2_hash_alg_to_string(hash_alg
);
4654 size_t info_len
= strlen(label
) + 1 + context_u_size
+ context_v_size
;
4655 _cleanup_free_
void *info
= malloc(info_len
);
4657 return log_oom_debug();
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
);
4663 _cleanup_free_
void *buf
= NULL
;
4677 *ret_key
= TAKE_PTR(buf
);
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
,
4690 TPM2B_PUBLIC
*ret
) {
4699 log_debug("Calculating public part of sealed object.");
4701 struct iovec data
[] = {
4702 IOVEC_MAKE((void*) seed
->buffer
, seed
->size
),
4703 IOVEC_MAKE((void*) secret
, secret_size
),
4705 TPM2B_DIGEST unique
;
4706 r
= tpm2_digest_many(
4707 parent
->publicArea
.nameAlg
,
4711 /* extend= */ false);
4715 *ret
= (TPM2B_PUBLIC
) {
4716 .size
= sizeof(TPMT_PUBLIC
),
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
,
4730 static int tpm2_calculate_seal_private(
4731 const TPM2B_PUBLIC
*parent
,
4732 const TPM2B_NAME
*name
,
4734 const TPM2B_DIGEST
*seed
,
4737 TPM2B_PRIVATE
*ret
) {
4748 log_debug("Calculating private part of sealed object.");
4750 _cleanup_free_
void *storage_key
= NULL
;
4751 size_t storage_key_size
;
4752 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4758 (size_t) parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
4762 return log_debug_errno(r
, "Could not calculate storage key KDFa: %m");
4764 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
4768 size_t bits
= (size_t) r
* 8;
4770 _cleanup_free_
void *integrity_key
= NULL
;
4771 size_t integrity_key_size
;
4772 r
= tpm2_kdfa(parent
->publicArea
.nameAlg
,
4776 /* context= */ NULL
,
4780 &integrity_key_size
);
4782 return log_debug_errno(r
, "Could not calculate integrity key KDFa: %m");
4784 TPM2B_AUTH auth
= {};
4786 r
= tpm2_get_pin_auth(parent
->publicArea
.nameAlg
, pin
, &auth
);
4791 TPM2B_SENSITIVE sensitive
= {
4792 .size
= sizeof(TPMT_SENSITIVE
),
4794 .sensitiveType
= TPM2_ALG_KEYEDHASH
,
4797 .sensitive
.bits
= TPM2B_SENSITIVE_DATA_MAKE(secret
, secret_size
),
4801 _cleanup_free_
void *marshalled_sensitive
= malloc(sizeof(sensitive
));
4802 if (!marshalled_sensitive
)
4803 return log_oom_debug();
4805 size_t marshalled_sensitive_size
= 0;
4806 rc
= sym_Tss2_MU_TPM2B_SENSITIVE_Marshal(
4808 marshalled_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
));
4815 const char *sym_alg
= tpm2_sym_alg_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.algorithm
);
4819 const char *sym_mode
= tpm2_sym_mode_to_string(parent
->publicArea
.parameters
.asymDetail
.symmetric
.mode
.sym
);
4823 _cleanup_free_
void *encrypted_sensitive
= NULL
;
4824 size_t encrypted_sensitive_size
;
4827 parent
->publicArea
.parameters
.asymDetail
.symmetric
.keyBits
.sym
,
4829 storage_key
, storage_key_size
,
4830 /* iv= */ NULL
, /* n_iv= */ 0,
4831 marshalled_sensitive
, marshalled_sensitive_size
,
4832 &encrypted_sensitive
, &encrypted_sensitive_size
);
4836 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
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
),
4846 r
= openssl_hmac_many(
4851 ELEMENTSOF(hmac_data
),
4857 TPM2B_DIGEST outer_hmac
= TPM2B_DIGEST_MAKE(hmac_buffer
, hmac_size
);
4859 TPM2B_PRIVATE
private = {};
4860 size_t private_size
= 0;
4861 rc
= sym_Tss2_MU_TPM2B_DIGEST_Marshal(
4864 sizeof(private.buffer
),
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
;
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
;
4880 static int tpm2_calculate_seal_rsa_seed(
4881 const TPM2B_PUBLIC
*parent
,
4883 size_t *ret_seed_size
,
4884 void **ret_encrypted_seed
,
4885 size_t *ret_encrypted_seed_size
) {
4891 assert(ret_seed_size
);
4892 assert(ret_encrypted_seed
);
4893 assert(ret_encrypted_seed_size
);
4895 log_debug("Calculating encrypted seed for RSA sealed object.");
4897 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
4898 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
4900 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4902 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
4906 size_t seed_size
= (size_t) r
;
4908 _cleanup_free_
void *seed
= malloc(seed_size
);
4910 return log_oom_debug();
4912 r
= crypto_random_bytes(seed
, seed_size
);
4914 return log_debug_errno(r
, "Failed to generate random seed: %m");
4916 const char *hash_alg_name
= tpm2_hash_alg_to_string(parent
->publicArea
.nameAlg
);
4920 _cleanup_free_
void *encrypted_seed
= NULL
;
4921 size_t encrypted_seed_size
;
4922 r
= rsa_oaep_encrypt_bytes(
4929 &encrypted_seed_size
);
4931 return log_debug_errno(r
, "Could not RSA-OAEP encrypt random seed: %m");
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
;
4941 static int tpm2_calculate_seal_ecc_seed(
4942 const TPM2B_PUBLIC
*parent
,
4944 size_t *ret_seed_size
,
4945 void **ret_encrypted_seed
,
4946 size_t *ret_encrypted_seed_size
) {
4953 assert(ret_seed_size
);
4954 assert(ret_encrypted_seed
);
4955 assert(ret_encrypted_seed_size
);
4957 log_debug("Calculating encrypted seed for ECC sealed object.");
4959 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*parent_pkey
= NULL
;
4960 r
= tpm2_tpm2b_public_to_openssl_pkey(parent
, &parent_pkey
);
4962 return log_debug_errno(r
, "Could not convert TPM2B_PUBLIC to OpenSSL PKEY: %m");
4965 r
= ecc_pkey_to_curve_x_y(
4968 /* ret_x= */ NULL
, /* ret_x_size= */ 0,
4969 /* ret_y= */ NULL
, /* ret_y_size= */ 0);
4973 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
4974 r
= ecc_pkey_new(curve_id
, &pkey
);
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
);
4982 return log_debug_errno(r
, "Could not generate ECC shared secret: %m");
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
);
4988 return log_debug_errno(r
, "Could not get ECC get x/y: %m");
4990 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(x_size
);
4992 return log_debug_errno(r
, "ECC point x size %zu is too large: %m", x_size
);
4994 r
= TPM2B_ECC_PARAMETER_CHECK_SIZE(y_size
);
4996 return log_debug_errno(r
, "ECC point y size %zu is too large: %m", y_size
);
4998 TPMS_ECC_POINT point
= {
4999 .x
= TPM2B_ECC_PARAMETER_MAKE(x
, x_size
),
5000 .y
= TPM2B_ECC_PARAMETER_MAKE(y
, y_size
),
5003 _cleanup_free_
void *encrypted_seed
= malloc(sizeof(point
));
5004 if (!encrypted_seed
)
5005 return log_oom_debug();
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
));
5013 r
= tpm2_hash_alg_to_size(parent
->publicArea
.nameAlg
);
5017 size_t bits
= (size_t) r
* 8;
5019 _cleanup_free_
void *seed
= NULL
;
5020 size_t seed_size
= 0; /* Explicit initialization to appease gcc */
5021 r
= tpm2_kdfe(parent
->publicArea
.nameAlg
,
5027 parent
->publicArea
.unique
.ecc
.x
.buffer
,
5028 parent
->publicArea
.unique
.ecc
.x
.size
,
5033 return log_debug_errno(r
, "Could not calculate KDFe: %m");
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
;
5043 static int tpm2_calculate_seal_seed(
5044 const TPM2B_PUBLIC
*parent
,
5045 TPM2B_DIGEST
*ret_seed
,
5046 TPM2B_ENCRYPTED_SECRET
*ret_encrypted_seed
) {
5052 assert(ret_encrypted_seed
);
5054 log_debug("Calculating encrypted seed for sealed object.");
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
);
5063 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5064 "Unsupported parent key type 0x%" PRIx16
, parent
->publicArea
.type
);
5066 return log_debug_errno(r
, "Could not calculate encrypted seed: %m");
5068 *ret_seed
= TPM2B_DIGEST_MAKE(seed
, seed_size
);
5069 *ret_encrypted_seed
= TPM2B_ENCRYPTED_SECRET_MAKE(encrypted_seed
, encrypted_seed_size
);
5074 #endif /* HAVE_OPENSSL */
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
,
5083 struct iovec
*ret_secret
,
5084 struct iovec
*ret_blob
,
5085 struct iovec
*ret_serialized_parent
) {
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 */
5095 assert(ret_serialized_parent
);
5097 log_debug("Calculating sealed object.");
5099 /* Default to the SRK. */
5100 if (parent_handle
== 0)
5101 parent_handle
= TPM2_SRK_HANDLE
;
5103 switch (TPM2_HANDLE_TYPE(parent_handle
)) {
5104 case TPM2_HT_PERSISTENT
:
5105 case TPM2_HT_NV_INDEX
:
5107 case TPM2_HT_TRANSIENT
:
5108 log_warning("Handle is transient, sealed secret may not be recoverable.");
5111 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5112 "Handle 0x%" PRIx32
" not persistent, transient, or NV.",
5116 _cleanup_(iovec_done_erase
) struct iovec generated_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
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();
5126 r
= crypto_random_bytes(generated_secret
.iov_base
, generated_secret
.iov_len
);
5128 return log_debug_errno(r
, "Failed to generate secret key: %m");
5130 secret
= &generated_secret
;
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
);
5138 TPM2B_DIGEST random_seed
;
5139 TPM2B_ENCRYPTED_SECRET seed
;
5140 r
= tpm2_calculate_seal_seed(parent_public
, &random_seed
, &seed
);
5144 TPM2B_PUBLIC
public;
5145 r
= tpm2_calculate_seal_public(parent_public
, attributes
, policy
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &public);
5150 r
= tpm2_calculate_pubkey_name(&public.publicArea
, &name
);
5154 TPM2B_PRIVATE
private;
5155 r
= tpm2_calculate_seal_private(parent_public
, &name
, pin
, &random_seed
, secret
->iov_base
, secret
->iov_len
, &private);
5159 _cleanup_(iovec_done
) struct iovec blob
= {};
5160 r
= tpm2_marshal_blob(&public, &private, &seed
, &blob
.iov_base
, &blob
.iov_len
);
5162 return log_debug_errno(r
, "Could not create sealed blob: %m");
5164 TPM2B_NAME parent_name
;
5165 r
= tpm2_calculate_pubkey_name(&parent_public
->publicArea
, &parent_name
);
5169 _cleanup_(iovec_done
) struct iovec serialized_parent
= {};
5170 r
= tpm2_calculate_serialize(
5174 &serialized_parent
.iov_base
,
5175 &serialized_parent
.iov_len
);
5180 *ret_secret
= TAKE_STRUCT(generated_secret
);
5181 *ret_blob
= TAKE_STRUCT(blob
);
5182 *ret_serialized_parent
= TAKE_STRUCT(serialized_parent
);
5185 #else /* HAVE_OPENSSL */
5186 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
5190 int tpm2_seal(Tpm2Context
*c
,
5191 uint32_t seal_key_handle
,
5192 const TPM2B_DIGEST
*policy
,
5194 struct iovec
*ret_secret
,
5195 struct iovec
*ret_blob
,
5196 uint16_t *ret_primary_alg
,
5197 struct iovec
*ret_srk
) {
5199 uint16_t primary_alg
= 0;
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.
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. */
5221 usec_t start
= now(CLOCK_MONOTONIC
);
5223 TPMA_OBJECT hmac_attributes
=
5224 TPMA_OBJECT_FIXEDTPM
|
5225 TPMA_OBJECT_FIXEDPARENT
;
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
;
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
),
5244 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
5245 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
5248 CLEANUP_ERASE(hmac_sensitive
);
5251 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &hmac_sensitive
.userAuth
);
5256 assert(sizeof(hmac_sensitive
.data
.buffer
) >= hmac_sensitive
.data
.size
);
5258 (void) tpm2_credit_random(c
);
5260 log_debug("Generating secret key data.");
5262 r
= crypto_random_bytes(hmac_sensitive
.data
.buffer
, hmac_sensitive
.data
.size
);
5264 return log_debug_errno(r
, "Failed to generate secret key: %m");
5266 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*primary_handle
= NULL
;
5268 _cleanup_(Esys_Freep
) TPM2B_PUBLIC
*primary_public
= NULL
;
5270 if (IN_SET(seal_key_handle
, 0, TPM2_SRK_HANDLE
)) {
5271 r
= tpm2_get_or_create_srk(
5273 /* session= */ NULL
,
5275 /* ret_name= */ NULL
,
5276 /* ret_qname= */ NULL
,
5280 } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle
), TPM2_HT_TRANSIENT
, TPM2_HT_PERSISTENT
)) {
5281 r
= tpm2_index_to_handle(
5284 /* session= */ NULL
,
5286 /* ret_name= */ NULL
,
5287 /* ret_qname= */ NULL
,
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
);
5296 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5297 "Seal key handle 0x%" PRIx32
" is neither transient nor persistent.",
5300 primary_alg
= primary_public
->publicArea
.type
;
5302 if (seal_key_handle
!= 0)
5303 log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
5305 /* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
5306 primary_alg
= TPM2_ALG_ECC
;
5308 TPM2B_PUBLIC
template = {
5309 .size
= sizeof(TPMT_PUBLIC
),
5311 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5313 return log_debug_errno(r
, "Could not get legacy ECC template: %m");
5315 if (!tpm2_supports_tpmt_public(c
, &template.publicArea
)) {
5316 primary_alg
= TPM2_ALG_RSA
;
5318 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5320 return log_debug_errno(r
, "Could not get legacy RSA template: %m");
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.");
5327 r
= tpm2_create_primary(
5329 /* session= */ NULL
,
5331 /* sensitive= */ NULL
,
5332 /* ret_public= */ NULL
,
5338 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5339 r
= tpm2_make_encryption_session(c
, primary_handle
, /* bind_key= */ NULL
, &encryption_session
);
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);
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
;
5355 log_debug("Marshalling private and public part of HMAC key.");
5357 _cleanup_(iovec_done
) struct iovec blob
= {};
5358 r
= tpm2_marshal_blob(public, private, /* seed= */ NULL
, &blob
.iov_base
, &blob
.iov_len
);
5360 return log_debug_errno(r
, "Could not create sealed blob: %m");
5363 log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5366 _cleanup_(iovec_done
) struct iovec srk
= {};
5367 _cleanup_(Esys_Freep
) void *tmp
= NULL
;
5370 r
= tpm2_serialize(c
, primary_handle
, &tmp
, &tmp_size
);
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.
5379 srk
.iov_base
= memdup(tmp
, tmp_size
);
5381 return log_oom_debug();
5382 srk
.iov_len
= tmp_size
;
5384 *ret_srk
= TAKE_STRUCT(srk
);
5387 *ret_secret
= TAKE_STRUCT(secret
);
5388 *ret_blob
= TAKE_STRUCT(blob
);
5390 if (ret_primary_alg
)
5391 *ret_primary_alg
= primary_alg
;
5396 #define RETRY_UNSEAL_MAX 30u
5398 int tpm2_unseal(Tpm2Context
*c
,
5399 uint32_t hash_pcr_mask
,
5401 const struct iovec
*pubkey
,
5402 uint32_t pubkey_pcr_mask
,
5403 JsonVariant
*signature
,
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
) {
5415 assert(iovec_is_set(blob
));
5416 assert(iovec_is_valid(known_policy_hash
));
5417 assert(iovec_is_valid(pubkey
));
5420 assert(TPM2_PCR_MASK_VALID(hash_pcr_mask
));
5421 assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask
));
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. */
5431 usec_t start
= now(CLOCK_MONOTONIC
);
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
);
5438 return log_debug_errno(r
, "Could not extract parts from blob: %m");
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
);
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
);
5453 } else if (primary_alg
!= 0) {
5454 TPM2B_PUBLIC
template = {
5455 .size
= sizeof(TPMT_PUBLIC
),
5457 r
= tpm2_get_legacy_template(primary_alg
, &template.publicArea
);
5459 return log_debug_errno(r
, "Could not get legacy template: %m");
5461 r
= tpm2_create_primary(
5463 /* session= */ NULL
,
5465 /* sensitive= */ NULL
,
5466 /* ret_public= */ NULL
,
5471 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
5472 "No SRK or primary alg provided.");
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
;
5479 /* session= */ NULL
,
5483 /* encryption_key= */ NULL
,
5484 /* symmetric= */ NULL
,
5489 private = *imported_private
;
5492 log_debug("Loading HMAC key into TPM.");
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.
5500 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*hmac_key
= NULL
;
5501 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &hmac_key
);
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
);
5510 return log_debug_errno(r
, "Could not create TPMT_PUBLIC: %m");
5512 r
= tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b
, &fp
.iov_base
, &fp
.iov_len
);
5514 return log_debug_errno(r
, "Could not get key fingerprint: %m");
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.
5524 r
= tpm2_set_auth(c
, hmac_key
, pin
);
5528 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*encryption_session
= NULL
;
5529 r
= tpm2_make_encryption_session(c
, primary_handle
, hmac_key
, &encryption_session
);
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(
5545 r
= tpm2_build_sealing_policy(
5550 iovec_is_set(pubkey
) ? &pubkey_tpm2b
: NULL
,
5551 fp
.iov_base
, fp
.iov_len
,
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) {
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;
5577 return log_debug_errno(SYNTHETIC_ERRNO(EPERM
),
5578 "Current policy digest does not match stored policy digest, cancelling "
5579 "TPM2 authentication attempt.");
5582 log_debug("Unsealing HMAC key.");
5584 rc
= sym_Esys_Unseal(
5586 hmac_key
->esys_handle
,
5587 policy_session
->esys_handle
,
5588 encryption_session
->esys_handle
, /* use HMAC session to enable parameter encryption */
5591 if (rc
== TSS2_RC_SUCCESS
)
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
);
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
;
5607 log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC
) - start
, 1));
5609 *ret_secret
= TAKE_STRUCT(secret
);
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);
5618 int tpm2_define_policy_nv_index(
5620 const Tpm2Handle
*session
,
5621 TPM2_HANDLE requested_nv_index
,
5622 const TPM2B_DIGEST
*write_policy
,
5624 const TPM2B_AUTH
*auth
,
5625 TPM2_HANDLE
*ret_nv_index
,
5626 Tpm2Handle
**ret_nv_handle
,
5627 TPM2B_NV_PUBLIC
*ret_nv_public
) {
5629 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*new_handle
= NULL
;
5634 assert(pin
|| auth
);
5636 r
= tpm2_handle_new(c
, &new_handle
);
5640 new_handle
->flush
= false; /* This is a persistent NV index, don't flush hence */
5642 TPM2B_AUTH _auth
= {};
5643 CLEANUP_ERASE(_auth
);
5646 r
= tpm2_get_pin_auth(TPM2_ALG_SHA256
, pin
, &_auth
);
5653 for (unsigned try = 0; try < 25U; try++) {
5654 TPM2_HANDLE nv_index
;
5656 if (requested_nv_index
!= 0)
5657 nv_index
= requested_nv_index
;
5659 nv_index
= generate_random_nv_index();
5661 TPM2B_NV_PUBLIC public_info
= {
5662 .size
= sizeof_field(TPM2B_NV_PUBLIC
, 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
),
5672 public_info
.nvPublic
.authPolicy
= *write_policy
;
5674 rc
= sym_Esys_NV_DefineSpace(
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
,
5682 &new_handle
->esys_handle
);
5684 if (rc
== TSS2_RC_SUCCESS
) {
5685 log_debug("NV Index 0x%" PRIx32
" successfully allocated.", nv_index
);
5688 *ret_nv_index
= nv_index
;
5691 *ret_nv_handle
= TAKE_PTR(new_handle
);
5694 *ret_nv_public
= public_info
;
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
));
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
);
5708 log_debug("NV index 0x%" PRIu32
" already taken, trying another one (%u tries left)", nv_index
, try);
5711 return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
5712 "Too many attempts trying to allocate NV index: %s", sym_Tss2_RC_Decode(rc
));
5715 int tpm2_write_policy_nv_index(
5717 const Tpm2Handle
*policy_session
,
5718 TPM2_HANDLE nv_index
,
5719 const Tpm2Handle
*nv_handle
,
5720 const TPM2B_DIGEST
*policy_digest
) {
5725 assert(policy_session
);
5727 assert(policy_digest
);
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.");
5733 .hashAlg
= TPM2_ALG_SHA256
,
5735 assert(policy_digest
->size
<= sizeof_field(TPMT_HA
, digest
));
5736 memcpy_safe(&ha
.digest
, policy_digest
->buffer
, policy_digest
->size
);
5738 TPM2B_MAX_NV_BUFFER buffer
= {};
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.");
5745 buffer
.size
= written
;
5747 rc
= sym_Esys_NV_Write(
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
,
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
));
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
);
5769 int tpm2_undefine_policy_nv_index(
5771 const Tpm2Handle
*session
,
5772 TPM2_HANDLE nv_index
,
5773 const Tpm2Handle
*nv_handle
) {
5780 rc
= sym_Esys_NV_UndefineSpace(
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
));
5791 log_debug("Undefined NV index 0x%x", nv_index
);
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
) {
5808 assert(primary_handle
);
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. */
5814 if (data
->iov_len
>= sizeof_field(TPMS_SENSITIVE_CREATE
, data
.buffer
))
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
),
5826 TPMS_SENSITIVE_CREATE hmac_sensitive
= {
5827 .data
.size
= hmac_template
.unique
.keyedHash
.size
,
5830 CLEANUP_ERASE(hmac_sensitive
);
5832 memcpy_safe(hmac_sensitive
.data
.buffer
, data
->iov_base
, data
->iov_len
);
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);
5840 _cleanup_(iovec_done
) struct iovec public_blob
= {}, private_blob
= {};
5842 r
= tpm2_marshal_private(private, &private_blob
.iov_base
, &private_blob
.iov_len
);
5846 r
= tpm2_marshal_public(public, &public_blob
.iov_base
, &public_blob
.iov_len
);
5851 *ret_public
= TAKE_STRUCT(public_blob
);
5853 *ret_private
= TAKE_STRUCT(private_blob
);
5858 int tpm2_unseal_data(
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
) {
5871 assert(public_blob
);
5872 assert(private_blob
);
5873 assert(primary_handle
);
5875 TPM2B_PUBLIC
public;
5876 r
= tpm2_unmarshal_public(public_blob
->iov_base
, public_blob
->iov_len
, &public);
5880 TPM2B_PRIVATE
private;
5881 r
= tpm2_unmarshal_private(private_blob
->iov_base
, private_blob
->iov_len
, &private);
5885 _cleanup_(tpm2_handle_freep
) Tpm2Handle
*what
= NULL
;
5886 r
= tpm2_load(c
, primary_handle
, NULL
, &public, &private, &what
);
5890 _cleanup_(Esys_Freep
) TPM2B_SENSITIVE_DATA
* unsealed
= NULL
;
5891 rc
= sym_Esys_Unseal(
5894 policy_session
? policy_session
->esys_handle
: ESYS_TR_NONE
,
5895 encryption_session
? encryption_session
->esys_handle
: ESYS_TR_NONE
,
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
));
5905 _cleanup_(iovec_done
) struct iovec d
= {};
5906 d
= IOVEC_MAKE(memdup(unsealed
->buffer
, unsealed
->size
), unsealed
->size
);
5908 explicit_bzero_safe(unsealed
->buffer
, unsealed
->size
);
5911 return log_oom_debug();
5913 *ret_data
= TAKE_STRUCT(d
);
5916 #endif /* HAVE_TPM2 */
5918 int tpm2_list_devices(void) {
5920 _cleanup_(table_unrefp
) Table
*t
= NULL
;
5921 _cleanup_closedir_
DIR *d
= NULL
;
5926 return log_error_errno(r
, "TPM2 support is not installed.");
5928 t
= table_new("path", "device", "driver");
5932 d
= opendir("/sys/class/tpmrm");
5934 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open /sys/class/tpmrm: %m");
5935 if (errno
!= ENOENT
)
5939 _cleanup_free_
char *device_path
= NULL
, *device
= NULL
, *driver_path
= NULL
, *driver
= NULL
, *node
= NULL
;
5942 de
= readdir_no_dot(d
);
5946 device_path
= path_join("/sys/class/tpmrm", de
->d_name
, "device");
5950 r
= readlink_malloc(device_path
, &device
);
5952 log_debug_errno(r
, "Failed to read device symlink %s, ignoring: %m", device_path
);
5954 driver_path
= path_join(device_path
, "driver");
5958 r
= readlink_malloc(driver_path
, &driver
);
5960 log_debug_errno(r
, "Failed to read driver symlink %s, ignoring: %m", driver_path
);
5963 node
= path_join("/dev", de
->d_name
);
5970 TABLE_STRING
, device
? last_path_component(device
) : NULL
,
5971 TABLE_STRING
, driver
? last_path_component(driver
) : NULL
);
5973 return table_log_add_error(r
);
5977 if (table_isempty(t
)) {
5978 log_info("No suitable TPM2 devices found.");
5982 r
= table_print(t
, stdout
);
5984 return log_error_errno(r
, "Failed to show device table: %m");
5988 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
5989 "TPM2 not supported on this build.");
5993 int tpm2_find_device_auto(char **ret
) {
5995 _cleanup_closedir_
DIR *d
= NULL
;
6000 return log_debug_errno(r
, "TPM2 support is not installed.");
6002 d
= opendir("/sys/class/tpmrm");
6004 log_debug_errno(errno
, "Failed to open /sys/class/tpmrm: %m");
6005 if (errno
!= ENOENT
)
6008 _cleanup_free_
char *node
= NULL
;
6013 de
= readdir_no_dot(d
);
6018 return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ
),
6019 "More than one TPM2 (tpmrm) device found.");
6021 node
= path_join("/dev", de
->d_name
);
6023 return log_oom_debug();
6027 *ret
= TAKE_PTR(node
);
6032 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "No TPM2 (tpmrm) device found.");
6034 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
6035 "TPM2 not supported on this build.");
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",
6047 DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type
, Tpm2UserspaceEventType
);
6049 const char *tpm2_userspace_log_path(void) {
6050 return secure_getenv("SYSTEMD_MEASURE_LOG_USERSPACE") ?: "/run/log/systemd/tpm2-measure.log";
6053 const char *tpm2_firmware_log_path(void) {
6054 return secure_getenv("SYSTEMD_MEASURE_LOG_FIRMWARE") ?: "/sys/kernel/security/tpm0/binary_bios_measurements";
6058 static int tpm2_userspace_log_open(void) {
6059 _cleanup_close_
int fd
= -EBADF
;
6064 e
= tpm2_userspace_log_path();
6065 (void) mkdir_parents(e
, 0755);
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);
6072 return log_debug_errno(errno
, "Failed to open TPM log file '%s' for writing, ignoring: %m", e
);
6074 if (flock(fd
, LOCK_EX
) < 0)
6075 return log_debug_errno(errno
, "Failed to lock TPM log file '%s', ignoring: %m", e
);
6077 if (fstat(fd
, &st
) < 0)
6078 return log_debug_errno(errno
, "Failed to fstat TPM log file '%s', ignoring: %m", e
);
6080 r
= stat_verify_regular(&st
);
6082 return log_debug_errno(r
, "TPM log file '%s' is not regular, ignoring: %m", e
);
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
);
6091 if (fchmod(fd
, 0600 | S_ISVTX
) < 0)
6092 return log_debug_errno(errno
, "Failed to chmod() TPM log file '%s', ignoring: %m", e
);
6097 static int tpm2_userspace_log(
6100 const TPML_DIGEST_VALUES
*values
,
6101 Tpm2UserspaceEventType event_type
,
6102 const char *description
) {
6104 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *array
= NULL
;
6105 _cleanup_free_
char *f
= NULL
;
6110 assert(values
->count
> 0);
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:
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.
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.
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.
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.
6137 if (fd
< 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */
6140 for (size_t i
= 0; i
< values
->count
; i
++) {
6141 const EVP_MD
*implementation
;
6144 assert_se(a
= tpm2_hash_alg_to_string(values
->digests
[i
].hashAlg
));
6145 assert_se(implementation
= EVP_get_digestbyname(a
));
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
)))));
6152 return log_debug_errno(r
, "Failed to append digest object to JSON array: %m");
6157 r
= sd_id128_get_boot(&boot_id
);
6159 return log_debug_errno(r
, "Failed to acquire boot ID: %m");
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
)))))));
6171 return log_debug_errno(r
, "Failed to build log record JSON: %m");
6173 r
= json_variant_format(v
, JSON_FORMAT_SEQ
, &f
);
6175 return log_debug_errno(r
, "Failed to format JSON: %m");
6177 if (lseek(fd
, 0, SEEK_END
) < 0)
6178 return log_debug_errno(errno
, "Failed to seek to end of JSON log: %m");
6180 r
= loop_write(fd
, f
, SIZE_MAX
);
6182 return log_debug_errno(r
, "Failed to write JSON data to log: %m");
6185 return log_debug_errno(errno
, "Failed to sync JSON data: %m");
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");
6193 return log_debug_errno(r
, "Failed to sync JSON log: %m");
6199 int tpm2_extend_bytes(
6207 Tpm2UserspaceEventType event_type
,
6208 const char *description
) {
6211 _cleanup_close_
int log_fd
= -EBADF
;
6212 TPML_DIGEST_VALUES values
= {};
6216 assert(data
|| data_size
== 0);
6217 assert(secret
|| secret_size
== 0);
6219 if (data_size
== SIZE_MAX
)
6220 data_size
= strlen(data
);
6221 if (secret_size
== SIZE_MAX
)
6222 secret_size
= strlen(secret
);
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
);
6227 if (strv_isempty(banks
))
6230 STRV_FOREACH(bank
, banks
) {
6231 const EVP_MD
*implementation
;
6234 assert_se(implementation
= EVP_get_digestbyname(*bank
));
6236 if (values
.count
>= ELEMENTSOF(values
.digests
))
6237 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG
), "Too many banks selected.");
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.");
6242 id
= tpm2_hash_alg_from_string(EVP_MD_name(implementation
));
6244 return log_debug_errno(id
, "Can't map hash name to TPM2.");
6246 values
.digests
[values
.count
].hashAlg
= id
;
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.");
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();
6267 rc
= sym_Esys_PCR_Extend(
6269 ESYS_TR_PCR0
+ pcr_index
,
6274 if (rc
!= TSS2_RC_SUCCESS
)
6275 return log_debug_errno(
6276 SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
6277 "Failed to measure into PCR %u: %s",
6279 sym_Tss2_RC_Decode(rc
));
6281 /* Now, write what we just extended to the log, too. */
6282 (void) tpm2_userspace_log(log_fd
, pcr_index
, &values
, event_type
, description
);
6285 #else /* HAVE_OPENSSL */
6286 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL support is disabled.");
6290 const uint16_t tpm2_hash_algorithms
[] = {
6298 assert_cc(ELEMENTSOF(tpm2_hash_algorithms
) == TPM2_N_HASH_ALGORITHMS
+ 1);
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
)
6308 TPM2B_DIGEST
*tpm2_pcr_prediction_result_get_hash(Tpm2PCRPredictionResult
*result
, uint16_t alg
) {
6313 alg_idx
= tpm2_hash_algorithm_index(alg
);
6314 if (alg_idx
== SIZE_MAX
) /* Algorithm not known? */
6317 if (result
->hash
[alg_idx
].size
<= 0) /* No hash value for this algorithm? */
6320 return result
->hash
+ alg_idx
;
6323 void tpm2_pcr_prediction_done(Tpm2PCRPrediction
*p
) {
6326 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++)
6327 ordered_set_free(p
->results
[pcr
]);
6330 static void tpm2_pcr_prediction_result_hash_func(const Tpm2PCRPredictionResult
*banks
, struct siphash
*state
) {
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
);
6337 static int tpm2_pcr_prediction_result_compare_func(const Tpm2PCRPredictionResult
*a
, const Tpm2PCRPredictionResult
*b
) {
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
);
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
,
6361 static Tpm2PCRPredictionResult
*find_prediction_result_by_algorithm(OrderedSet
*set
, Tpm2PCRPredictionResult
*result
, size_t alg_idx
) {
6362 Tpm2PCRPredictionResult
*f
;
6365 assert(alg_idx
!= SIZE_MAX
);
6367 f
= ordered_set_get(set
, result
); /* Full match? */
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) */
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)
6382 bool tpm2_pcr_prediction_equal(
6383 Tpm2PCRPrediction
*a
,
6384 Tpm2PCRPrediction
*b
,
6385 uint16_t algorithm
) {
6392 if (a
->pcrs
!= b
->pcrs
)
6395 size_t alg_idx
= tpm2_hash_algorithm_index(algorithm
);
6396 if (alg_idx
== SIZE_MAX
)
6399 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6400 Tpm2PCRPredictionResult
*banks
;
6402 ORDERED_SET_FOREACH(banks
, a
->results
[pcr
])
6403 if (!find_prediction_result_by_algorithm(b
->results
[pcr
], banks
, alg_idx
))
6406 ORDERED_SET_FOREACH(banks
, b
->results
[pcr
])
6407 if (!find_prediction_result_by_algorithm(a
->results
[pcr
], banks
, alg_idx
))
6414 int tpm2_pcr_prediction_to_json(
6415 const Tpm2PCRPrediction
*prediction
,
6417 JsonVariant
**ret
) {
6419 _cleanup_(json_variant_unrefp
) JsonVariant
*aj
= NULL
;
6425 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6426 _cleanup_(json_variant_unrefp
) JsonVariant
*vj
= NULL
;
6427 Tpm2PCRPredictionResult
*banks
;
6429 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6432 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6434 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6438 r
= json_variant_append_arrayb(
6440 JSON_BUILD_HEX(hash
->buffer
, hash
->size
));
6442 return log_error_errno(r
, "Failed to append hash variant to JSON array: %m");
6448 r
= json_variant_append_arrayb(
6451 JSON_BUILD_PAIR_INTEGER("pcr", pcr
),
6452 JSON_BUILD_PAIR_VARIANT("values", vj
)));
6454 return log_error_errno(r
, "Failed to append PCR variants to JSON array: %m");
6458 r
= json_variant_new_array(&aj
, NULL
, 0);
6463 *ret
= TAKE_PTR(aj
);
6467 int tpm2_pcr_prediction_from_json(
6468 Tpm2PCRPrediction
*prediction
,
6476 size_t alg_index
= tpm2_hash_algorithm_index(algorithm
);
6477 assert(alg_index
< TPM2_N_HASH_ALGORITHMS
);
6479 if (!json_variant_is_array(aj
))
6480 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR variant array is not an array.");
6483 JSON_VARIANT_ARRAY_FOREACH(pcr
, aj
) {
6484 JsonVariant
*nr
, *values
;
6486 nr
= json_variant_by_key(pcr
, "pcr");
6488 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks PCR index field");
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");
6494 values
= json_variant_by_key(pcr
, "values");
6496 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry lacks values field");
6498 if (!json_variant_is_array(values
))
6499 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG
), "PCR array entry values field is not an array");
6501 prediction
->pcrs
|= UINT32_C(1) << json_variant_unsigned(nr
);
6504 JSON_VARIANT_ARRAY_FOREACH(v
, values
) {
6505 _cleanup_free_
void *buffer
= NULL
;
6508 r
= json_variant_unhex(v
, &buffer
, &size
);
6510 return log_error_errno(r
, "Failed to decode PCR policy array hash value");
6513 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is zero.");
6515 if (size
> sizeof_field(TPM2B_DIGEST
, buffer
))
6516 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "PCR policy array hash value is too large.");
6518 _cleanup_free_ Tpm2PCRPredictionResult
*banks
= new0(Tpm2PCRPredictionResult
, 1);
6522 memcpy(banks
->hash
[alg_index
].buffer
, buffer
, size
);
6523 banks
->hash
[alg_index
].size
= size
;
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 */
6529 return log_error_errno(r
, "Failed to insert result into set: %m");
6538 int tpm2_calculate_policy_super_pcr(
6539 Tpm2PCRPrediction
*prediction
,
6541 TPM2B_DIGEST
*pcr_policy
) {
6545 assert_se(prediction
);
6546 assert_se(pcr_policy
);
6548 /* Start with a zero policy if not specified otherwise. */
6549 TPM2B_DIGEST super_pcr_policy_digest
= *pcr_policy
;
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
))
6558 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6561 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6563 Tpm2PCRPredictionResult
*banks
= ASSERT_PTR(ordered_set_first(prediction
->results
[pcr
]));
6565 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6569 if (!GREEDY_REALLOC(single_values
, n_single_values
+ 1))
6572 single_values
[n_single_values
++] = TPM2_PCR_VALUE_MAKE(pcr
, algorithm
, *hash
);
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(
6580 &super_pcr_policy_digest
);
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
;
6591 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
6594 if (ordered_set_size(prediction
->results
[pcr
]) <= 1) /* We only care for PCRs with 2 or more variants in this loop */
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.");
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
;
6604 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6608 /* Evolve it based on the expected PCR value for this PCR */
6609 r
= tpm2_calculate_policy_pcr(
6610 &TPM2_PCR_VALUE_MAKE(
6614 /* n_pcr_values= */ 1,
6615 &pcr_policy_digest
);
6619 /* Store away this new variant */
6620 if (!GREEDY_REALLOC(pcr_policy_digest_variants
, n_pcr_policy_digest_variants
+ 1))
6623 pcr_policy_digest_variants
[n_pcr_policy_digest_variants
++] = pcr_policy_digest
;
6625 log_debug("Calculated PCR policy variant %zu for PCR %" PRIu32
, n_pcr_policy_digest_variants
, pcr
);
6628 assert_se(n_pcr_policy_digest_variants
>= 2);
6629 assert_se(n_pcr_policy_digest_variants
<= 8);
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
);
6639 log_debug("Combined %zu variants in OR policy.", n_pcr_policy_digest_variants
);
6642 *pcr_policy
= super_pcr_policy_digest
;
6646 int tpm2_policy_super_pcr(
6648 const Tpm2Handle
*session
,
6649 const Tpm2PCRPrediction
*prediction
,
6650 uint16_t algorithm
) {
6656 assert_se(prediction
);
6658 TPM2B_DIGEST previous_policy_digest
= TPM2B_DIGEST_MAKE(NULL
, TPM2_SHA256_DIGEST_SIZE
);
6660 uint32_t single_value_pcrs
= 0;
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
))
6667 if (ordered_set_size(prediction
->results
[pcr
]) != 1)
6670 log_debug("Including PCR %" PRIu32
" in single value PolicyPCR expression", pcr
);
6672 single_value_pcrs
|= UINT32_C(1) << pcr
;
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
);
6679 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6680 r
= tpm2_policy_pcr(
6684 ¤t_policy_digest
);
6688 previous_policy_digest
= *current_policy_digest
;
6691 for (uint32_t pcr
= 0; pcr
< TPM2_PCRS_MAX
; pcr
++) {
6694 if (!FLAGS_SET(prediction
->pcrs
, UINT32_C(1) << pcr
))
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");
6701 if (n_branches
== 1) /* Single choice PCRs are already covered by the loop above */
6704 log_debug("Submitting PCR/OR policy for PCR %" PRIu32
, pcr
);
6706 TPML_PCR_SELECTION pcr_selection
;
6707 tpm2_tpml_pcr_selection_from_mask(UINT32_C(1) << pcr
, algorithm
, &pcr_selection
);
6709 _cleanup_free_ TPM2B_DIGEST
*current_policy_digest
= NULL
;
6710 r
= tpm2_policy_pcr(
6714 ¤t_policy_digest
);
6718 _cleanup_free_ TPM2B_DIGEST
*branches
= NULL
;
6719 branches
= new0(TPM2B_DIGEST
, n_branches
);
6723 Tpm2PCRPredictionResult
*banks
;
6725 ORDERED_SET_FOREACH(banks
, prediction
->results
[pcr
]) {
6726 TPM2B_DIGEST pcr_policy_digest
= previous_policy_digest
;
6728 TPM2B_DIGEST
*hash
= tpm2_pcr_prediction_result_get_hash(banks
, algorithm
);
6732 /* Evolve it based on the expected PCR value for this PCR */
6733 r
= tpm2_calculate_policy_pcr(
6734 &TPM2_PCR_VALUE_MAKE(
6738 /* n_pcr_values= */ 1,
6739 &pcr_policy_digest
);
6743 branches
[i
++] = pcr_policy_digest
;
6746 assert_se(i
== n_branches
);
6748 current_policy_digest
= mfree(current_policy_digest
);
6754 ¤t_policy_digest
);
6758 previous_policy_digest
= *current_policy_digest
;
6764 void tpm2_pcrlock_policy_done(Tpm2PCRLockPolicy
*data
) {
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
);
6776 static int json_dispatch_tpm2_algorithm(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
6777 uint16_t *algorithm
= ASSERT_PTR(userdata
);
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
));
6788 int tpm2_pcrlock_search_file(const char *path
, FILE **ret_file
, char **ret_path
) {
6789 static const char search
[] =
6791 "/var/lib/systemd\0";
6796 path
= "pcrlock.json";
6798 r
= search_and_fopen_nulstr(path
, ret_file
? "re" : NULL
, NULL
, search
, ret_file
, ret_path
);
6800 return log_debug_errno(r
, "Failed to find TPM2 pcrlock policy file '%s': %m", path
);
6805 int tpm2_pcrlock_policy_from_json(
6807 Tpm2PCRLockPolicy
*ret_policy
) {
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
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
},
6824 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy policy
= {};
6830 r
= json_dispatch(v
, policy_dispatch
, JSON_LOG
, &policy
);
6834 r
= tpm2_pcr_prediction_from_json(&policy
.prediction
, policy
.algorithm
, policy
.prediction_json
);
6838 *ret_policy
= TAKE_STRUCT(policy
);
6842 int tpm2_pcrlock_policy_load(
6844 Tpm2PCRLockPolicy
*ret_policy
) {
6846 _cleanup_free_
char *discovered_path
= NULL
;
6847 _cleanup_fclose_
FILE *f
= NULL
;
6850 r
= tpm2_pcrlock_search_file(path
, &f
, &discovered_path
);
6852 *ret_policy
= (Tpm2PCRLockPolicy
) {};
6856 return log_error_errno(r
, "Failed to load TPM2 pcrlock policy file: %m");
6858 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
6859 r
= json_parse_file(
6864 /* ret_line= */ NULL
,
6865 /* ret_column= */ NULL
);
6867 return log_error_errno(r
, "Failed to parse existing pcrlock policy file '%s': %m", discovered_path
);
6869 return tpm2_pcrlock_policy_from_json(v
, ret_policy
);
6872 static int pcrlock_policy_load_credential(
6874 const struct iovec
*data
,
6875 Tpm2PCRLockPolicy
*ret
) {
6877 _cleanup_free_
char *c
= NULL
;
6886 ascii_strlower(c
); /* Lowercase, to match what we did at encryption time */
6888 _cleanup_(iovec_done
) struct iovec decoded
= {};
6889 r
= decrypt_credential_and_warn(
6891 now(CLOCK_REALTIME
),
6892 /* tpm2_device= */ NULL
,
6893 /* tpm2_signature_path= */ NULL
,
6896 CREDENTIAL_ALLOW_NULL
,
6901 if (memchr(decoded
.iov_base
, 0, decoded
.iov_len
))
6902 return log_error_errno(r
, "Credential '%s' contains embedded NUL byte, refusing.", name
);
6904 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
6905 r
= json_parse(decoded
.iov_base
,
6908 /* ret_line= */ NULL
,
6909 /* ret_column= */ NULL
);
6911 return log_error_errno(r
, "Failed to parse pcrlock policy: %m");
6913 r
= tpm2_pcrlock_policy_from_json(v
, ret
);
6920 int tpm2_pcrlock_policy_from_credentials(
6921 const struct iovec
*srk
,
6922 const struct iovec
*nv
,
6923 Tpm2PCRLockPolicy
*ret
) {
6925 _cleanup_close_
int dfd
= -EBADF
;
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. */
6934 const char *cp
= secure_getenv("SYSTEMD_ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY") ?: ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
;
6936 dfd
= open(cp
, O_CLOEXEC
|O_DIRECTORY
);
6938 if (errno
== ENOENT
) {
6939 log_debug("No encrypted system credentials passed.");
6943 return log_error_errno(errno
, "Faile to open system credentials directory.");
6946 _cleanup_free_ DirectoryEntries
*de
= NULL
;
6947 r
= readdir_all(dfd
, RECURSE_DIR_IGNORE_DOT
, &de
);
6949 return log_error_errno(r
, "Failed to enumerate system credentials: %m");
6951 FOREACH_ARRAY(i
, de
->entries
, de
->n_entries
) {
6952 _cleanup_(iovec_done
) struct iovec data
= {};
6953 struct dirent
*d
= *i
;
6955 if (!startswith_no_case(d
->d_name
, "pcrlock.")) /* VFAT is case-insensitive, hence don't be too strict here */
6958 r
= read_full_file_full(
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
,
6969 log_warning_errno(r
, "Failed to read credentials file %s/%s, skipping: %m", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
6973 _cleanup_(tpm2_pcrlock_policy_done
) Tpm2PCRLockPolicy loaded_policy
= {};
6974 r
= pcrlock_policy_load_credential(
6979 log_warning_errno(r
, "Loading of pcrlock policy from credential '%s/%s' failed, skipping.", ENCRYPTED_SYSTEM_CREDENTIALS_DIRECTORY
, d
->d_name
);
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
);
6990 log_info("No pcrlock policy found among system credentials.");
6991 *ret
= (Tpm2PCRLockPolicy
) {};
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
;
7007 return log_debug_errno(r
, "TPM2 support not installed: %m");
7009 r
= read_full_file(path
, &device_key_buffer
, &device_key_buffer_size
);
7011 return log_error_errno(r
, "Failed to read device key from file '%s': %m", path
);
7014 rc
= sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(
7015 (uint8_t*) device_key_buffer
,
7016 device_key_buffer_size
,
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.");
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
);
7029 *ret
= device_key_public
;
7034 char *tpm2_pcr_mask_to_string(uint32_t mask
) {
7035 _cleanup_free_
char *s
= NULL
;
7037 FOREACH_PCR_IN_MASK(n
, mask
)
7038 if (strextendf_with_separator(&s
, "+", "%d", n
) < 0)
7047 int tpm2_make_pcr_json_array(uint32_t pcr_mask
, JsonVariant
**ret
) {
7048 _cleanup_(json_variant_unrefp
) JsonVariant
*a
= NULL
;
7053 for (size_t i
= 0; i
< TPM2_PCRS_MAX
; i
++) {
7054 _cleanup_(json_variant_unrefp
) JsonVariant
*e
= NULL
;
7056 if ((pcr_mask
& (UINT32_C(1) << i
)) == 0)
7059 r
= json_variant_new_integer(&e
, i
);
7063 r
= json_variant_append_array(&a
, e
);
7069 return json_variant_new_array(ret
, NULL
, 0);
7075 int tpm2_parse_pcr_json_array(JsonVariant
*v
, uint32_t *ret
) {
7079 if (!json_variant_is_array(v
))
7080 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR array is not a JSON array.");
7082 JSON_VARIANT_ARRAY_FOREACH(e
, v
) {
7085 if (!json_variant_is_unsigned(e
))
7086 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR is not an unsigned integer.");
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
);
7092 mask
|= UINT32_C(1) << u
;
7101 int tpm2_make_luks2_json(
7103 uint32_t hash_pcr_mask
,
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
,
7114 JsonVariant
**ret
) {
7116 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
, *hmj
= NULL
, *pkmj
= NULL
;
7117 _cleanup_free_
char *keyslot_as_string
= NULL
;
7120 assert(iovec_is_valid(pubkey
));
7121 assert(iovec_is_valid(blob
));
7122 assert(iovec_is_valid(policy_hash
));
7124 if (asprintf(&keyslot_as_string
, "%i", keyslot
) < 0)
7127 r
= tpm2_make_pcr_json_array(hash_pcr_mask
, &hmj
);
7131 if (pubkey_pcr_mask
!= 0) {
7132 r
= tpm2_make_pcr_json_array(pubkey_pcr_mask
, &pkmj
);
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. */
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
))));
7166 int tpm2_parse_luks2_json(
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
) {
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;
7192 keyslot
= cryptsetup_get_keyslot_from_token(v
);
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
7197 log_debug_errno(keyslot
, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
7202 w
= json_variant_by_key(v
, "tpm2-pcrs");
7204 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-pcrs' field.");
7206 r
= tpm2_parse_pcr_json_array(w
, &hash_pcr_mask
);
7208 return log_debug_errno(r
, "Failed to parse TPM2 PCR mask: %m");
7210 /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
7212 w
= json_variant_by_key(v
, "tpm2-pcr-bank");
7214 /* The PCR bank field is optional */
7216 if (!json_variant_is_string(w
))
7217 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PCR bank is not a string.");
7219 r
= tpm2_hash_alg_from_string(json_variant_string(w
));
7221 return log_debug_errno(r
, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w
));
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");
7230 /* The primary key algorithm is optional */
7232 if (!json_variant_is_string(w
))
7233 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 primary key algorithm is not a string.");
7235 r
= tpm2_asym_alg_from_string(json_variant_string(w
));
7237 return log_debug_errno(r
, "TPM2 asymmetric algorithm invalid or not supported: %s", json_variant_string(w
));
7242 w
= json_variant_by_key(v
, "tpm2-blob");
7244 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-blob' field.");
7246 r
= json_variant_unbase64_iovec(w
, &blob
);
7248 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-blob' field.");
7250 w
= json_variant_by_key(v
, "tpm2-policy-hash");
7252 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 token data lacks 'tpm2-policy-hash' field.");
7254 r
= json_variant_unhex_iovec(w
, &policy_hash
);
7256 return log_debug_errno(r
, "Invalid base64 data in 'tpm2-policy-hash' field.");
7258 w
= json_variant_by_key(v
, "tpm2-pin");
7260 if (!json_variant_is_boolean(w
))
7261 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 PIN policy is not a boolean.");
7263 SET_FLAG(flags
, TPM2_FLAGS_USE_PIN
, json_variant_boolean(w
));
7266 w
= json_variant_by_key(v
, "tpm2_pcrlock");
7268 if (!json_variant_is_boolean(w
))
7269 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "TPM2 pclock policy is not a boolean.");
7271 SET_FLAG(flags
, TPM2_FLAGS_USE_PCRLOCK
, json_variant_boolean(w
));
7274 w
= json_variant_by_key(v
, "tpm2_salt");
7276 r
= json_variant_unbase64_iovec(w
, &salt
);
7278 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_salt' field.");
7281 w
= json_variant_by_key(v
, "tpm2_pubkey_pcrs");
7283 r
= tpm2_parse_pcr_json_array(w
, &pubkey_pcr_mask
);
7288 w
= json_variant_by_key(v
, "tpm2_pubkey");
7290 r
= json_variant_unbase64_iovec(w
, &pubkey
);
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.");
7296 w
= json_variant_by_key(v
, "tpm2_srk");
7298 r
= json_variant_unbase64_iovec(w
, &srk
);
7300 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_srk' field.");
7303 w
= json_variant_by_key(v
, "tpm2_pcrlock_nv");
7305 r
= json_variant_unbase64_iovec(w
, &pcrlock_nv
);
7307 return log_debug_errno(r
, "Invalid base64 data in 'tpm2_pcrlock_nv' field.");
7311 *ret_keyslot
= keyslot
;
7312 if (ret_hash_pcr_mask
)
7313 *ret_hash_pcr_mask
= hash_pcr_mask
;
7315 *ret_pcr_bank
= pcr_bank
;
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
;
7323 *ret_blob
= TAKE_STRUCT(blob
);
7324 if (ret_policy_hash
)
7325 *ret_policy_hash
= TAKE_STRUCT(policy_hash
);
7327 *ret_salt
= TAKE_STRUCT(salt
);
7329 *ret_srk
= TAKE_STRUCT(srk
);
7331 *ret_pcrlock_nv
= TAKE_STRUCT(pcrlock_nv
);
7337 int tpm2_hash_alg_to_size(uint16_t alg
) {
7341 case TPM2_ALG_SHA256
:
7343 case TPM2_ALG_SHA384
:
7345 case TPM2_ALG_SHA512
:
7348 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown hash algorithm id 0x%" PRIx16
, alg
);
7352 const char *tpm2_hash_alg_to_string(uint16_t alg
) {
7356 case TPM2_ALG_SHA256
:
7358 case TPM2_ALG_SHA384
:
7360 case TPM2_ALG_SHA512
:
7363 log_debug("Unknown hash algorithm id 0x%" PRIx16
, alg
);
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
);
7380 const char *tpm2_asym_alg_to_string(uint16_t alg
) {
7387 log_debug("Unknown asymmetric algorithm id 0x%" PRIx16
, alg
);
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
);
7400 const char *tpm2_sym_alg_to_string(uint16_t alg
) {
7407 log_debug("Unknown symmetric algorithm id 0x%" PRIx16
, alg
);
7412 int tpm2_sym_alg_from_string(const char *alg
) {
7414 if (strcaseeq_ptr(alg
, "aes"))
7415 return TPM2_ALG_AES
;
7417 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric algorithm name '%s'", alg
);
7420 const char *tpm2_sym_mode_to_string(uint16_t mode
) {
7435 log_debug("Unknown symmetric mode id 0x%" PRIx16
, mode
);
7440 int tpm2_sym_mode_from_string(const char *mode
) {
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
;
7453 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown symmetric mode name '%s'", mode
);
7456 Tpm2Support
tpm2_support(void) {
7457 Tpm2Support support
= TPM2_SUPPORT_NONE
;
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. */
7465 r
= dir_is_empty("/sys/class/tpmrm", /* ignore_hidden_or_backup= */ false);
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
;
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
;
7478 support
|= TPM2_SUPPORT_FIRMWARE
;
7481 support
|= TPM2_SUPPORT_SYSTEM
;
7485 support
|= TPM2_SUPPORT_LIBRARIES
;
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
)
7496 default_hash
= v
->hash
;
7500 if (default_hash
!= 0)
7501 FOREACH_ARRAY(v
, pcr_values
, n_pcr_values
)
7503 v
->hash
= default_hash
;
7507 /* The following tpm2_parse_pcr_argument*() functions all log errors, to match the behavior of system-wide
7508 * parse_*_argument() functions. */
7510 /* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
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.
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
) {
7523 assert(ret_pcr_values
);
7524 assert(ret_n_pcr_values
);
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
);
7530 return log_error_errno(r
, "Could not parse PCR values from '%s': %m", arg
);
7532 tpm2_pcr_values_apply_default_hash_alg(pcr_values
, n_pcr_values
);
7534 tpm2_sort_pcr_values(pcr_values
, n_pcr_values
);
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.");
7539 *ret_pcr_values
= TAKE_PTR(pcr_values
);
7540 *ret_n_pcr_values
= n_pcr_values
;
7544 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
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
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
) {
7562 assert(n_pcr_values
);
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
);
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
))
7574 tpm2_pcr_values_apply_default_hash_alg(more_pcr_values
, n_more_pcr_values
);
7576 tpm2_sort_pcr_values(more_pcr_values
, n_more_pcr_values
);
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.");
7581 SWAP_TWO(*pcr_values
, more_pcr_values
);
7582 *n_pcr_values
= n_more_pcr_values
;
7586 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
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
) {
7596 _cleanup_free_ Tpm2PCRValue
*pcr_values
= NULL
;
7597 size_t n_pcr_values
;
7603 r
= tpm2_parse_pcr_argument(arg
, &pcr_values
, &n_pcr_values
);
7607 if (n_pcr_values
== 0) {
7608 /* This retains the previous behavior of clearing the mask if the arg is empty */
7614 r
= tpm2_pcr_values_hash_count(pcr_values
, n_pcr_values
, &hash_count
);
7616 return log_error_errno(r
, "Could not get hash count from pcr values: %m");
7619 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Multiple PCR hash banks selected.");
7622 r
= tpm2_pcr_values_to_mask(pcr_values
, n_pcr_values
, pcr_values
[0].hash
, &new_mask
);
7624 return log_error_errno(r
, "Could not get pcr values mask: %m");
7626 if (*ret_mask
== UINT32_MAX
)
7627 *ret_mask
= new_mask
;
7629 *ret_mask
|= new_mask
;
7633 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "TPM2 support is disabled.");
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
;
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. */
7646 search
= strv_split_nulstr(CONF_PATHS_NULSTR("systemd"));
7648 return log_oom_debug();
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. */
7655 path
= "tpm2-pcr-signature.json";
7658 if (strv_extend(&search
, "/.extra") < 0)
7659 return log_oom_debug();
7662 r
= search_and_fopen(path
, "re", NULL
, (const char**) search
, &f
, &discovered_path
);
7664 return log_debug_errno(r
, "Failed to find TPM PCR signature file '%s': %m", path
);
7666 r
= json_parse_file(f
, discovered_path
, 0, ret
, NULL
, NULL
);
7668 return log_debug_errno(r
, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path
);
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
;
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. */
7682 path
= "tpm2-pcr-public-key.pem";
7684 r
= search_and_fopen(path
, "re", NULL
, (const char**) CONF_PATHS_STRV("systemd"), &f
, &discovered_path
);
7686 return log_debug_errno(r
, "Failed to find TPM PCR public key file '%s': %m", path
);
7688 r
= read_full_stream(f
, (char**) ret_pubkey
, ret_pubkey_size
);
7690 return log_debug_errno(r
, "Failed to load TPM PCR public key PEM file '%s': %m", discovered_path
);
7695 #define PBKDF2_HMAC_SHA256_ITERATIONS 10000
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
7702 * - https://en.wikipedia.org/wiki/PBKDF2
7703 * - https://www.rfc-editor.org/rfc/rfc2898#section-5.2
7705 int tpm2_util_pbkdf2_hmac_sha256(const void *pass
,
7709 uint8_t ret_key
[static SHA256_DIGEST_SIZE
]) {
7711 _cleanup_(erase_and_freep
) uint8_t *buffer
= NULL
;
7712 uint8_t u
[SHA256_DIGEST_SIZE
];
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.
7719 static const uint8_t block_cnt
[] = { 0, 0, 0, 1 };
7722 assert (saltlen
> 0);
7723 assert (saltlen
<= (SIZE_MAX
- sizeof(block_cnt
)));
7724 assert (passlen
> 0);
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.
7730 buffer
= malloc(saltlen
+ sizeof(block_cnt
));
7734 memcpy(buffer
, salt
, saltlen
);
7735 memcpy(&buffer
[saltlen
], block_cnt
, sizeof(block_cnt
));
7737 hmac_sha256(pass
, passlen
, buffer
, saltlen
+ sizeof(block_cnt
), u
);
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
;
7743 for (size_t i
= 1; i
< PBKDF2_HMAC_SHA256_ITERATIONS
; i
++) {
7744 hmac_sha256(pass
, passlen
, u
, sizeof(u
), u
);
7746 for (size_t j
=0; j
< sizeof(u
); j
++)
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",
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);