if (r < 0)
return log_error_errno(r, "Invalid pcr hash value '%s': %m", p);
- pcr_value.value.size = buf_size;
- assert(sizeof(pcr_value.value.buffer) >= pcr_value.value.size);
- memcpy(pcr_value.value.buffer, buf, pcr_value.value.size);
+ r = TPM2B_DIGEST_CHECK_SIZE(buf_size);
+ if (r < 0)
+ return log_error_errno(r, "PCR hash value size %zu too large.", buf_size);
+
+ pcr_value.value = TPM2B_DIGEST_MAKE(buf, buf_size);
}
*ret_pcr_value = pcr_value;
if (r < 0)
return r;
+ r = TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(signature_size);
+ if (r < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
+
TPMT_SIGNATURE policy_signature = {
.sigAlg = TPM2_ALG_RSASSA,
.signature.rsassa = {
.hash = TPM2_ALG_SHA256,
- .sig.size = signature_size,
+ .sig = TPM2B_PUBLIC_KEY_RSA_MAKE(signature_raw, signature_size),
},
};
- if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer))
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
- memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
rc = sym_Esys_VerifySignature(
c->esys_context,
int tpm2_seal(const char *device, uint32_t hash_pcr_mask, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, const char *pin, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_pcr_hash, size_t *ret_pcr_hash_size, uint16_t *ret_pcr_bank, uint16_t *ret_primary_alg, void **ret_srk_buf, size_t *ret_srk_buf_size);
int tpm2_unseal(const char *device, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, JsonVariant *signature, const char *pin, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, const void *srk_buf, size_t srk_buf_size, void **ret_secret, size_t *ret_secret_size);
+/* The tpm2-tss library has many structs that are simply a combination of an array (or object) and
+ * size. These macros allow easily initializing or assigning instances of such structs from an existing
+ * buffer/object and size, while also checking the size for safety with the struct buffer/object size. If the
+ * provided buffer/object is NULL, the resulting struct's buffer/object will be 0s. If the provided size is
+ * larger than the struct's buffer/object size, this results in assertion failure; to check the size, use one
+ * of the TPM2B_*_CHECK_SIZE() macros. */
+#define TPM2B_AUTH_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_AUTH, buffer, size)
+#define TPM2B_DATA_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_DATA, buffer, size)
+#define TPM2B_DIGEST_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_DIGEST, buffer, size)
+#define TPM2B_ECC_PARAMETER_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_ECC_PARAMETER, buffer, size)
+#define TPM2B_ENCRYPTED_SECRET_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_ENCRYPTED_SECRET, secret, size)
+#define TPM2B_MAX_BUFFER_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_MAX_BUFFER, buffer, size)
+#define TPM2B_NAME_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_NAME, name, size)
+#define TPM2B_PRIVATE_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_PRIVATE, buffer, size)
+#define TPM2B_PRIVATE_KEY_RSA_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_PRIVATE_KEY_RSA, buffer, size)
+#define TPM2B_PUBLIC_KEY_RSA_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_PUBLIC_KEY_RSA, buffer, size)
+#define TPM2B_SENSITIVE_DATA_MAKE(b, s) TPM2B_BUF_SIZE_STRUCT_MAKE(b, s, TPM2B_SENSITIVE_DATA, buffer, size)
+#define TPM2B_BUF_SIZE_STRUCT_MAKE(buf, size, struct_type, buffer_field, size_field) \
+ _TPM2B_BUF_SIZE_STRUCT_MAKE(buf, size, UNIQ, struct_type, buffer_field, size_field)
+#define _TPM2B_BUF_SIZE_STRUCT_MAKE(buf, size, uniq, struct_type, buffer_field, size_field) \
+ ({ \
+ typeof(buf) UNIQ_T(BUF, uniq) = (buf); \
+ typeof(size) UNIQ_T(SIZE, uniq) = (size); \
+ struct_type UNIQ_T(STRUCT, uniq) = { .size_field = UNIQ_T(SIZE, uniq), }; \
+ assert(sizeof(UNIQ_T(STRUCT, uniq).buffer_field) >= (size_t) UNIQ_T(SIZE, uniq)); \
+ if (UNIQ_T(BUF, uniq)) \
+ memcpy(UNIQ_T(STRUCT, uniq).buffer_field, UNIQ_T(BUF, uniq), UNIQ_T(SIZE, uniq)); \
+ UNIQ_T(STRUCT, uniq); \
+ })
+
+/* Check if the size will fit in the TPM2B struct buffer. Returns 0 if the size will fit, otherwise this logs
+ * a debug message and returns < 0. */
+#define TPM2B_AUTH_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_AUTH, buffer)
+#define TPM2B_DATA_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_DATA, buffer)
+#define TPM2B_DIGEST_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_DIGEST, buffer)
+#define TPM2B_ECC_PARAMETER_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_ECC_PARAMETER, buffer)
+#define TPM2B_ENCRYPTED_SECRET_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_ENCRYPTED_SECRET, buffer)
+#define TPM2B_MAX_BUFFER_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_MAX_BUFFER, buffer)
+#define TPM2B_NAME_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_NAME, name)
+#define TPM2B_PRIVATE_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_PRIVATE, buffer)
+#define TPM2B_PRIVATE_KEY_RSA_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_PRIVATE_KEY_RSA, buffer)
+#define TPM2B_PUBLIC_KEY_RSA_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_PUBLIC_KEY_RSA, buffer)
+#define TPM2B_SENSITIVE_DATA_CHECK_SIZE(s) TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(s, TPM2B_SENSITIVE_DATA, buffer)
+#define TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(size, struct_type, buffer_field) \
+ _TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(size, UNIQ, struct_type, buffer_field)
+#define _TPM2B_BUF_SIZE_STRUCT_CHECK_SIZE(size, uniq, struct_type, buffer_field) \
+ ({ \
+ size_t UNIQ_T(SIZE, uniq) = (size_t) (size); \
+ size_t UNIQ_T(BUFSIZE, uniq) = sizeof_field(struct_type, buffer_field); \
+ UNIQ_T(BUFSIZE, uniq) < UNIQ_T(SIZE, uniq) ? \
+ log_debug_errno(SYNTHETIC_ERRNO(EINVAL), \
+ "Size %zu larger than " #struct_type " buffer size %zu.", \
+ UNIQ_T(SIZE, uniq), UNIQ_T(BUFSIZE, uniq)) : \
+ 0; \
+ })
+
#else /* HAVE_TPM2 */
typedef struct {} Tpm2Context;
typedef struct {} Tpm2Handle;