tpm2-util: more iovec'ification
Let's move more code to using struct iovec for passing around binary chunks of data. No real changes in behaviour, just refactoring.
This commit is contained in:
+130
-159
@@ -138,14 +138,13 @@ int read_credential(const char *name, void **ret, size_t *ret_size) {
|
||||
}
|
||||
|
||||
int read_credential_with_decryption(const char *name, void **ret, size_t *ret_size) {
|
||||
_cleanup_(iovec_done_erase) struct iovec ret_iovec = {};
|
||||
_cleanup_(erase_and_freep) void *data = NULL;
|
||||
_cleanup_free_ char *fn = NULL;
|
||||
size_t sz = 0;
|
||||
const char *d;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* Just like read_credential() but will also look for encrypted credentials. Note that services only
|
||||
* receive decrypted credentials, hence use read_credential() for those. This helper here is for
|
||||
* generators, i.e. code that runs outside of service context, and thus has no decrypted credentials
|
||||
@@ -193,18 +192,21 @@ int read_credential_with_decryption(const char *name, void **ret, size_t *ret_si
|
||||
now(CLOCK_REALTIME),
|
||||
/* tpm2_device = */ NULL,
|
||||
/* tpm2_signature_path = */ NULL,
|
||||
data,
|
||||
sz,
|
||||
ret,
|
||||
ret_size);
|
||||
&IOVEC_MAKE(data, sz),
|
||||
&ret_iovec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(ret_iovec.iov_base);
|
||||
if (ret_size)
|
||||
*ret_size = ret_iovec.iov_len;
|
||||
|
||||
return 1; /* found */
|
||||
|
||||
not_found:
|
||||
*ret = NULL;
|
||||
|
||||
if (ret)
|
||||
*ret = NULL;
|
||||
if (ret_size)
|
||||
*ret_size = 0;
|
||||
|
||||
@@ -352,8 +354,7 @@ static int make_credential_host_secret(
|
||||
CredentialSecretFlags flags,
|
||||
const char *dirname,
|
||||
const char *fn,
|
||||
void **ret_data,
|
||||
size_t *ret_size) {
|
||||
struct iovec *ret) {
|
||||
|
||||
_cleanup_free_ char *t = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
@@ -420,7 +421,7 @@ static int make_credential_host_secret(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ret_data) {
|
||||
if (ret) {
|
||||
void *copy;
|
||||
|
||||
copy = memdup(buf.data, sizeof(buf.data));
|
||||
@@ -429,12 +430,9 @@ static int make_credential_host_secret(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*ret_data = copy;
|
||||
*ret = IOVEC_MAKE(copy, sizeof(buf.data));
|
||||
}
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = sizeof(buf.data);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -444,7 +442,7 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size) {
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret) {
|
||||
_cleanup_free_ char *_dirname = NULL, *_filename = NULL;
|
||||
_cleanup_close_ int dfd = -EBADF;
|
||||
sd_id128_t machine_id;
|
||||
@@ -512,7 +510,7 @@ int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *
|
||||
"Failed to open %s/%s: %m", dirname, filename);
|
||||
|
||||
|
||||
r = make_credential_host_secret(dfd, machine_id, flags, dirname, filename, ret, ret_size);
|
||||
r = make_credential_host_secret(dfd, machine_id, flags, dirname, filename, ret);
|
||||
if (r == -EEXIST) {
|
||||
log_debug_errno(r, "Credential secret %s/%s appeared while we were creating it, rereading.",
|
||||
dirname, filename);
|
||||
@@ -579,12 +577,9 @@ int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *
|
||||
if (!copy)
|
||||
return log_oom_debug();
|
||||
|
||||
*ret = copy;
|
||||
*ret = IOVEC_MAKE(copy, sz);
|
||||
}
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = sz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -683,17 +678,15 @@ struct _packed_ metadata_credential_header {
|
||||
#define CREDENTIAL_FIELD_SIZE_MAX (16U*1024U)
|
||||
|
||||
static int sha256_hash_host_and_tpm2_key(
|
||||
const void *host_key,
|
||||
size_t host_key_size,
|
||||
const void *tpm2_key,
|
||||
size_t tpm2_key_size,
|
||||
const struct iovec *host_key,
|
||||
const struct iovec *tpm2_key,
|
||||
uint8_t ret[static SHA256_DIGEST_LENGTH]) {
|
||||
|
||||
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *md = NULL;
|
||||
unsigned l;
|
||||
|
||||
assert(host_key_size == 0 || host_key);
|
||||
assert(tpm2_key_size == 0 || tpm2_key);
|
||||
assert(iovec_is_valid(host_key));
|
||||
assert(iovec_is_valid(tpm2_key));
|
||||
assert(ret);
|
||||
|
||||
/* Combines the host key and the TPM2 HMAC hash into a SHA256 hash value we'll use as symmetric encryption key. */
|
||||
@@ -705,10 +698,10 @@ static int sha256_hash_host_and_tpm2_key(
|
||||
if (EVP_DigestInit_ex(md, EVP_sha256(), NULL) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initial SHA256 context.");
|
||||
|
||||
if (host_key && EVP_DigestUpdate(md, host_key, host_key_size) != 1)
|
||||
if (iovec_is_set(host_key) && EVP_DigestUpdate(md, host_key->iov_base, host_key->iov_len) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash host key.");
|
||||
|
||||
if (tpm2_key && EVP_DigestUpdate(md, tpm2_key, tpm2_key_size) != 1)
|
||||
if (iovec_is_set(tpm2_key) && EVP_DigestUpdate(md, tpm2_key->iov_base, tpm2_key->iov_len) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash TPM2 key.");
|
||||
|
||||
assert(EVP_MD_CTX_size(md) == SHA256_DIGEST_LENGTH);
|
||||
@@ -729,28 +722,23 @@ int encrypt_credential_and_warn(
|
||||
uint32_t tpm2_hash_pcr_mask,
|
||||
const char *tpm2_pubkey_path,
|
||||
uint32_t tpm2_pubkey_pcr_mask,
|
||||
const void *input,
|
||||
size_t input_size,
|
||||
void **ret,
|
||||
size_t *ret_size) {
|
||||
const struct iovec *input,
|
||||
struct iovec *ret) {
|
||||
|
||||
_cleanup_(iovec_done) struct iovec tpm2_blob = {}, tpm2_policy_hash = {}, iv = {}, pubkey = {};
|
||||
_cleanup_(iovec_done_erase) struct iovec tpm2_key = {}, output = {}, host_key = {};
|
||||
_cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
|
||||
_cleanup_(erase_and_freep) void *host_key = NULL, *tpm2_key = NULL;
|
||||
size_t host_key_size = 0, tpm2_key_size = 0, tpm2_blob_size = 0, tpm2_policy_hash_size = 0, output_size, p, ml;
|
||||
_cleanup_free_ void *tpm2_blob = NULL, *tpm2_policy_hash = NULL, *iv = NULL, *output = NULL;
|
||||
_cleanup_free_ struct metadata_credential_header *m = NULL;
|
||||
uint16_t tpm2_pcr_bank = 0, tpm2_primary_alg = 0;
|
||||
struct encrypted_credential_header *h;
|
||||
int ksz, bsz, ivsz, tsz, added, r;
|
||||
_cleanup_free_ void *pubkey = NULL;
|
||||
size_t pubkey_size = 0;
|
||||
uint8_t md[SHA256_DIGEST_LENGTH];
|
||||
const EVP_CIPHER *cc;
|
||||
sd_id128_t id;
|
||||
size_t p, ml;
|
||||
|
||||
assert(input || input_size == 0);
|
||||
assert(iovec_is_valid(input));
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
|
||||
if (!sd_id128_in_set(with_key,
|
||||
_CRED_AUTO,
|
||||
@@ -790,8 +778,7 @@ int encrypt_credential_and_warn(
|
||||
CREDENTIAL_SECRET_GENERATE|
|
||||
CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED|
|
||||
(sd_id128_equal(with_key, _CRED_AUTO) ? CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS : 0),
|
||||
&host_key,
|
||||
&host_key_size);
|
||||
&host_key);
|
||||
if (r == -ENOMEDIUM && sd_id128_equal(with_key, _CRED_AUTO))
|
||||
log_debug_errno(r, "Credential host secret location on temporary file system, not using.");
|
||||
else if (r < 0)
|
||||
@@ -824,7 +811,7 @@ int encrypt_credential_and_warn(
|
||||
|
||||
/* Load public key for PCR policies, if one is specified, or explicitly requested */
|
||||
|
||||
r = tpm2_load_pcr_public_key(tpm2_pubkey_path, &pubkey, &pubkey_size);
|
||||
r = tpm2_load_pcr_public_key(tpm2_pubkey_path, &pubkey.iov_base, &pubkey.iov_len);
|
||||
if (r < 0) {
|
||||
if (tpm2_pubkey_path || r != -ENOENT || !sd_id128_in_set(with_key, _CRED_AUTO, _CRED_AUTO_INITRD))
|
||||
return log_error_errno(r, "Failed read TPM PCR public key: %m");
|
||||
@@ -833,7 +820,7 @@ int encrypt_credential_and_warn(
|
||||
}
|
||||
}
|
||||
|
||||
if (!pubkey)
|
||||
if (!iovec_is_set(&pubkey))
|
||||
tpm2_pubkey_pcr_mask = 0;
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
@@ -855,8 +842,8 @@ int encrypt_credential_and_warn(
|
||||
return log_error_errno(r, "Could not read PCR values: %m");
|
||||
|
||||
TPM2B_PUBLIC public;
|
||||
if (pubkey) {
|
||||
r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &public);
|
||||
if (iovec_is_set(&pubkey)) {
|
||||
r = tpm2_tpm2b_public_from_pem(pubkey.iov_base, pubkey.iov_len, &public);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m");
|
||||
}
|
||||
@@ -865,7 +852,7 @@ int encrypt_credential_and_warn(
|
||||
r = tpm2_calculate_sealing_policy(
|
||||
tpm2_hash_pcr_values,
|
||||
tpm2_n_hash_pcr_values,
|
||||
pubkey ? &public : NULL,
|
||||
iovec_is_set(&pubkey) ? &public : NULL,
|
||||
/* use_pin= */ false,
|
||||
/* pcrlock_policy= */ NULL,
|
||||
&tpm2_policy);
|
||||
@@ -876,11 +863,10 @@ int encrypt_credential_and_warn(
|
||||
/* seal_key_handle= */ 0,
|
||||
&tpm2_policy,
|
||||
/* pin= */ NULL,
|
||||
&tpm2_key, &tpm2_key_size,
|
||||
&tpm2_blob, &tpm2_blob_size,
|
||||
&tpm2_key,
|
||||
&tpm2_blob,
|
||||
&tpm2_primary_alg,
|
||||
/* ret_srk_buf= */ NULL,
|
||||
/* ret_srk_buf_size= */ NULL);
|
||||
/* ret_srk= */ NULL);
|
||||
if (r < 0) {
|
||||
if (sd_id128_equal(with_key, _CRED_AUTO_INITRD))
|
||||
log_warning("TPM2 present and used, but we didn't manage to talk to it. Credential will be refused if SecureBoot is enabled.");
|
||||
@@ -890,25 +876,22 @@ int encrypt_credential_and_warn(
|
||||
log_notice_errno(r, "TPM2 sealing didn't work, continuing without TPM2: %m");
|
||||
}
|
||||
|
||||
tpm2_policy_hash_size = tpm2_policy.size;
|
||||
tpm2_policy_hash = malloc(tpm2_policy_hash_size);
|
||||
if (!tpm2_policy_hash)
|
||||
if (!iovec_memdup(&IOVEC_MAKE(tpm2_policy.buffer, tpm2_policy.size), &tpm2_policy_hash))
|
||||
return log_oom();
|
||||
memcpy(tpm2_policy_hash, tpm2_policy.buffer, tpm2_policy_hash_size);
|
||||
|
||||
assert(tpm2_blob_size <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
assert(tpm2_policy_hash_size <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
assert(tpm2_blob.iov_len <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
assert(tpm2_policy_hash.iov_len <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sd_id128_in_set(with_key, _CRED_AUTO, _CRED_AUTO_INITRD)) {
|
||||
/* Let's settle the key type in auto mode now. */
|
||||
|
||||
if (host_key && tpm2_key)
|
||||
id = pubkey ? CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC;
|
||||
else if (tpm2_key)
|
||||
id = pubkey ? CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK : CRED_AES256_GCM_BY_TPM2_HMAC;
|
||||
else if (host_key)
|
||||
if (iovec_is_set(&host_key) && iovec_is_set(&tpm2_key))
|
||||
id = iovec_is_set(&pubkey) ? CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC;
|
||||
else if (iovec_is_set(&tpm2_key))
|
||||
id = iovec_is_set(&pubkey) ? CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK : CRED_AES256_GCM_BY_TPM2_HMAC;
|
||||
else if (iovec_is_set(&host_key))
|
||||
id = CRED_AES256_GCM_BY_HOST;
|
||||
else if (sd_id128_equal(with_key, _CRED_AUTO_INITRD))
|
||||
id = CRED_AES256_GCM_BY_NULL;
|
||||
@@ -922,7 +905,7 @@ int encrypt_credential_and_warn(
|
||||
log_warning("Using a null key for encryption and signing. Confidentiality or authenticity will not be provided.");
|
||||
|
||||
/* Let's now take the host key and the TPM2 key and hash it together, to use as encryption key for the data */
|
||||
r = sha256_hash_host_and_tpm2_key(host_key, host_key_size, tpm2_key, tpm2_key_size, md);
|
||||
r = sha256_hash_host_and_tpm2_key(&host_key, &tpm2_key, md);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -939,11 +922,13 @@ int encrypt_credential_and_warn(
|
||||
if (ivsz > 0) {
|
||||
assert((size_t) ivsz <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
|
||||
iv = malloc(ivsz);
|
||||
if (!iv)
|
||||
iv.iov_base = malloc(ivsz);
|
||||
if (!iv.iov_base)
|
||||
return log_oom();
|
||||
|
||||
r = crypto_random_bytes(iv, ivsz);
|
||||
iv.iov_len = ivsz;
|
||||
|
||||
r = crypto_random_bytes(iv.iov_base, iv.iov_len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquired randomized IV: %m");
|
||||
}
|
||||
@@ -955,61 +940,61 @@ int encrypt_credential_and_warn(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate encryption object: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (EVP_EncryptInit_ex(context, cc, NULL, md, iv) != 1)
|
||||
if (EVP_EncryptInit_ex(context, cc, NULL, md, iv.iov_base) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize encryption context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
/* Just an upper estimate */
|
||||
output_size =
|
||||
output.iov_len =
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz) +
|
||||
ALIGN8(tpm2_key ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob_size + tpm2_policy_hash_size : 0) +
|
||||
ALIGN8(pubkey ? offsetof(struct tpm2_public_key_credential_header, data) + pubkey_size : 0) +
|
||||
ALIGN8(iovec_is_set(&tpm2_key) ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob.iov_len + tpm2_policy_hash.iov_len : 0) +
|
||||
ALIGN8(iovec_is_set(&pubkey) ? offsetof(struct tpm2_public_key_credential_header, data) + pubkey.iov_len : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name) + strlen_ptr(name)) +
|
||||
input_size + 2U * (size_t) bsz +
|
||||
input->iov_len + 2U * (size_t) bsz +
|
||||
tsz;
|
||||
|
||||
output = malloc0(output_size);
|
||||
if (!output)
|
||||
output.iov_base = malloc0(output.iov_len);
|
||||
if (!output.iov_base)
|
||||
return log_oom();
|
||||
|
||||
h = (struct encrypted_credential_header*) output;
|
||||
h = (struct encrypted_credential_header*) output.iov_base;
|
||||
h->id = id;
|
||||
h->block_size = htole32(bsz);
|
||||
h->key_size = htole32(ksz);
|
||||
h->tag_size = htole32(tsz);
|
||||
h->iv_size = htole32(ivsz);
|
||||
memcpy(h->iv, iv, ivsz);
|
||||
memcpy(h->iv, iv.iov_base, ivsz);
|
||||
|
||||
p = ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz);
|
||||
|
||||
if (tpm2_key) {
|
||||
if (iovec_is_set(&tpm2_key)) {
|
||||
struct tpm2_credential_header *t;
|
||||
|
||||
t = (struct tpm2_credential_header*) ((uint8_t*) output + p);
|
||||
t = (struct tpm2_credential_header*) ((uint8_t*) output.iov_base + p);
|
||||
t->pcr_mask = htole64(tpm2_hash_pcr_mask);
|
||||
t->pcr_bank = htole16(tpm2_pcr_bank);
|
||||
t->primary_alg = htole16(tpm2_primary_alg);
|
||||
t->blob_size = htole32(tpm2_blob_size);
|
||||
t->policy_hash_size = htole32(tpm2_policy_hash_size);
|
||||
memcpy(t->policy_hash_and_blob, tpm2_blob, tpm2_blob_size);
|
||||
memcpy(t->policy_hash_and_blob + tpm2_blob_size, tpm2_policy_hash, tpm2_policy_hash_size);
|
||||
t->blob_size = htole32(tpm2_blob.iov_len);
|
||||
t->policy_hash_size = htole32(tpm2_policy_hash.iov_len);
|
||||
memcpy(t->policy_hash_and_blob, tpm2_blob.iov_base, tpm2_blob.iov_len);
|
||||
memcpy(t->policy_hash_and_blob + tpm2_blob.iov_len, tpm2_policy_hash.iov_base, tpm2_policy_hash.iov_len);
|
||||
|
||||
p += ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob_size + tpm2_policy_hash_size);
|
||||
p += ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob.iov_len + tpm2_policy_hash.iov_len);
|
||||
}
|
||||
|
||||
if (pubkey) {
|
||||
if (iovec_is_set(&pubkey)) {
|
||||
struct tpm2_public_key_credential_header *z;
|
||||
|
||||
z = (struct tpm2_public_key_credential_header*) ((uint8_t*) output + p);
|
||||
z = (struct tpm2_public_key_credential_header*) ((uint8_t*) output.iov_base + p);
|
||||
z->pcr_mask = htole64(tpm2_pubkey_pcr_mask);
|
||||
z->size = htole32(pubkey_size);
|
||||
memcpy(z->data, pubkey, pubkey_size);
|
||||
z->size = htole32(pubkey.iov_len);
|
||||
memcpy(z->data, pubkey.iov_base, pubkey.iov_len);
|
||||
|
||||
p += ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + pubkey_size);
|
||||
p += ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + pubkey.iov_len);
|
||||
}
|
||||
|
||||
/* Pass the encrypted + TPM2 header as AAD */
|
||||
if (EVP_EncryptUpdate(context, NULL, &added, output, p) != 1)
|
||||
if (EVP_EncryptUpdate(context, NULL, &added, output.iov_base, p) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
@@ -1025,53 +1010,52 @@ int encrypt_credential_and_warn(
|
||||
memcpy_safe(m->name, name, ml);
|
||||
|
||||
/* And encrypt the metadata header */
|
||||
if (EVP_EncryptUpdate(context, (uint8_t*) output + p, &added, (const unsigned char*) m, ALIGN8(offsetof(struct metadata_credential_header, name) + ml)) != 1)
|
||||
if (EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, (const unsigned char*) m, ALIGN8(offsetof(struct metadata_credential_header, name) + ml)) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt metadata header: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
assert(added >= 0);
|
||||
assert((size_t) added <= output_size - p);
|
||||
assert((size_t) added <= output.iov_len - p);
|
||||
p += added;
|
||||
|
||||
/* Then encrypt the plaintext */
|
||||
if (EVP_EncryptUpdate(context, (uint8_t*) output + p, &added, input, input_size) != 1)
|
||||
if (EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, input->iov_base, input->iov_len) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt data: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
assert(added >= 0);
|
||||
assert((size_t) added <= output_size - p);
|
||||
assert((size_t) added <= output.iov_len - p);
|
||||
p += added;
|
||||
|
||||
/* Finalize */
|
||||
if (EVP_EncryptFinal_ex(context, (uint8_t*) output + p, &added) != 1)
|
||||
if (EVP_EncryptFinal_ex(context, (uint8_t*) output.iov_base + p, &added) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize data encryption: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
assert(added >= 0);
|
||||
assert((size_t) added <= output_size - p);
|
||||
assert((size_t) added <= output.iov_len - p);
|
||||
p += added;
|
||||
|
||||
assert(p <= output_size - tsz);
|
||||
assert(p <= output.iov_len - tsz);
|
||||
|
||||
/* Append tag */
|
||||
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, tsz, (uint8_t*) output + p) != 1)
|
||||
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, tsz, (uint8_t*) output.iov_base + p) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get tag: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
p += tsz;
|
||||
assert(p <= output_size);
|
||||
assert(p <= output.iov_len);
|
||||
output.iov_len = p;
|
||||
|
||||
if (DEBUG_LOGGING && input_size > 0) {
|
||||
if (DEBUG_LOGGING && input->iov_len > 0) {
|
||||
size_t base64_size;
|
||||
|
||||
base64_size = DIV_ROUND_UP(p * 4, 3); /* Include base64 size increase in debug output */
|
||||
assert(base64_size >= input_size);
|
||||
log_debug("Input of %zu bytes grew to output of %zu bytes (+%2zu%%).", input_size, base64_size, base64_size * 100 / input_size - 100);
|
||||
base64_size = DIV_ROUND_UP(output.iov_len * 4, 3); /* Include base64 size increase in debug output */
|
||||
assert(base64_size >= input->iov_len);
|
||||
log_debug("Input of %zu bytes grew to output of %zu bytes (+%2zu%%).", input->iov_len, base64_size, base64_size * 100 / input->iov_len - 100);
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(output);
|
||||
*ret_size = p;
|
||||
|
||||
*ret = TAKE_STRUCT(output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1080,30 +1064,27 @@ int decrypt_credential_and_warn(
|
||||
usec_t validate_timestamp,
|
||||
const char *tpm2_device,
|
||||
const char *tpm2_signature_path,
|
||||
const void *input,
|
||||
size_t input_size,
|
||||
void **ret,
|
||||
size_t *ret_size) {
|
||||
const struct iovec *input,
|
||||
struct iovec *ret) {
|
||||
|
||||
_cleanup_(erase_and_freep) void *host_key = NULL, *tpm2_key = NULL, *plaintext = NULL;
|
||||
_cleanup_(iovec_done_erase) struct iovec host_key = {}, plaintext = {}, tpm2_key = {};
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *signature_json = NULL;
|
||||
_cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
|
||||
size_t host_key_size = 0, tpm2_key_size = 0, plaintext_size, p, hs;
|
||||
struct encrypted_credential_header *h;
|
||||
struct metadata_credential_header *m;
|
||||
uint8_t md[SHA256_DIGEST_LENGTH];
|
||||
bool with_tpm2, with_tpm2_pk, with_host_key, with_null;
|
||||
const EVP_CIPHER *cc;
|
||||
size_t p, hs;
|
||||
int r, added;
|
||||
|
||||
assert(input || input_size == 0);
|
||||
assert(iovec_is_valid(input));
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
|
||||
h = (struct encrypted_credential_header*) input;
|
||||
h = (struct encrypted_credential_header*) input->iov_base;
|
||||
|
||||
/* The ID must fit in, for the current and all future formats */
|
||||
if (input_size < sizeof(h->id))
|
||||
if (input->iov_len < sizeof(h->id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
|
||||
|
||||
with_host_key = sd_id128_in_set(h->id, CRED_AES256_GCM_BY_HOST, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK);
|
||||
@@ -1141,7 +1122,7 @@ int decrypt_credential_and_warn(
|
||||
}
|
||||
|
||||
/* Now we know the minimum header size */
|
||||
if (input_size < offsetof(struct encrypted_credential_header, iv))
|
||||
if (input->iov_len < offsetof(struct encrypted_credential_header, iv))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
|
||||
|
||||
/* Verify some basic header values */
|
||||
@@ -1156,7 +1137,7 @@ int decrypt_credential_and_warn(
|
||||
|
||||
/* Ensure we have space for the full header now (we don't know the size of the name hence this is a
|
||||
* lower limit only) */
|
||||
if (input_size <
|
||||
if (input->iov_len <
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
|
||||
ALIGN8(with_tpm2 ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) : 0) +
|
||||
ALIGN8(with_tpm2_pk ? offsetof(struct tpm2_public_key_credential_header, data) : 0) +
|
||||
@@ -1168,7 +1149,7 @@ int decrypt_credential_and_warn(
|
||||
|
||||
if (with_tpm2) {
|
||||
#if HAVE_TPM2
|
||||
struct tpm2_credential_header* t = (struct tpm2_credential_header*) ((uint8_t*) input + p);
|
||||
struct tpm2_credential_header* t = (struct tpm2_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
struct tpm2_public_key_credential_header *z = NULL;
|
||||
|
||||
if (!TPM2_PCR_MASK_VALID(t->pcr_mask))
|
||||
@@ -1184,7 +1165,7 @@ int decrypt_credential_and_warn(
|
||||
|
||||
/* Ensure we have space for the full TPM2 header now (still don't know the name, and its size
|
||||
* though, hence still just a lower limit test only) */
|
||||
if (input_size <
|
||||
if (input->iov_len <
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
|
||||
ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + le32toh(t->blob_size) + le32toh(t->policy_hash_size)) +
|
||||
ALIGN8(with_tpm2_pk ? offsetof(struct tpm2_public_key_credential_header, data) : 0) +
|
||||
@@ -1197,14 +1178,14 @@ int decrypt_credential_and_warn(
|
||||
le32toh(t->policy_hash_size));
|
||||
|
||||
if (with_tpm2_pk) {
|
||||
z = (struct tpm2_public_key_credential_header*) ((uint8_t*) input + p);
|
||||
z = (struct tpm2_public_key_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
|
||||
if (!TPM2_PCR_MASK_VALID(le64toh(z->pcr_mask)) || le64toh(z->pcr_mask) == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range.");
|
||||
if (le32toh(z->size) > PUBLIC_KEY_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected public key size.");
|
||||
|
||||
if (input_size <
|
||||
if (input->iov_len <
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
|
||||
ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + le32toh(t->blob_size) + le32toh(t->policy_hash_size)) +
|
||||
ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + le32toh(z->size)) +
|
||||
@@ -1226,21 +1207,16 @@ int decrypt_credential_and_warn(
|
||||
r = tpm2_unseal(tpm2_context,
|
||||
le64toh(t->pcr_mask),
|
||||
le16toh(t->pcr_bank),
|
||||
z ? z->data : NULL,
|
||||
z ? le32toh(z->size) : 0,
|
||||
z ? &IOVEC_MAKE(z->data, le32toh(z->size)) : NULL,
|
||||
z ? le64toh(z->pcr_mask) : 0,
|
||||
signature_json,
|
||||
/* pin= */ NULL,
|
||||
/* pcrlock_policy= */ NULL,
|
||||
le16toh(t->primary_alg),
|
||||
t->policy_hash_and_blob,
|
||||
le32toh(t->blob_size),
|
||||
t->policy_hash_and_blob + le32toh(t->blob_size),
|
||||
le32toh(t->policy_hash_size),
|
||||
/* srk_buf= */ NULL,
|
||||
/* srk_buf_size= */ 0,
|
||||
&tpm2_key,
|
||||
&tpm2_key_size);
|
||||
&IOVEC_MAKE(t->policy_hash_and_blob, le32toh(t->blob_size)),
|
||||
&IOVEC_MAKE(t->policy_hash_and_blob + le32toh(t->blob_size), le32toh(t->policy_hash_size)),
|
||||
/* srk= */ NULL,
|
||||
&tpm2_key);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
|
||||
#else
|
||||
@@ -1249,10 +1225,7 @@ int decrypt_credential_and_warn(
|
||||
}
|
||||
|
||||
if (with_host_key) {
|
||||
r = get_credential_host_secret(
|
||||
0,
|
||||
&host_key,
|
||||
&host_key_size);
|
||||
r = get_credential_host_secret(/* flags= */ 0, &host_key);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine local credential key: %m");
|
||||
}
|
||||
@@ -1260,7 +1233,7 @@ int decrypt_credential_and_warn(
|
||||
if (with_null)
|
||||
log_warning("Warning: using a null key for decryption and authentication. Confidentiality or authenticity are not provided.");
|
||||
|
||||
sha256_hash_host_and_tpm2_key(host_key, host_key_size, tpm2_key, tpm2_key_size, md);
|
||||
sha256_hash_host_and_tpm2_key(&host_key, &tpm2_key, md);
|
||||
|
||||
assert_se(cc = EVP_aes_256_gcm());
|
||||
|
||||
@@ -1287,41 +1260,41 @@ int decrypt_credential_and_warn(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set IV and key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (EVP_DecryptUpdate(context, NULL, &added, input, p) != 1)
|
||||
if (EVP_DecryptUpdate(context, NULL, &added, input->iov_base, p) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
plaintext = malloc(input_size - p - le32toh(h->tag_size));
|
||||
if (!plaintext)
|
||||
plaintext.iov_base = malloc(input->iov_len - p - le32toh(h->tag_size));
|
||||
if (!plaintext.iov_base)
|
||||
return -ENOMEM;
|
||||
|
||||
if (EVP_DecryptUpdate(
|
||||
context,
|
||||
plaintext,
|
||||
plaintext.iov_base,
|
||||
&added,
|
||||
(uint8_t*) input + p,
|
||||
input_size - p - le32toh(h->tag_size)) != 1)
|
||||
(uint8_t*) input->iov_base + p,
|
||||
input->iov_len - p - le32toh(h->tag_size)) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decrypt data: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
assert(added >= 0);
|
||||
assert((size_t) added <= input_size - p - le32toh(h->tag_size));
|
||||
plaintext_size = added;
|
||||
assert((size_t) added <= input->iov_len - p - le32toh(h->tag_size));
|
||||
plaintext.iov_len = added;
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input + input_size - le32toh(h->tag_size)) != 1)
|
||||
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input->iov_base + input->iov_len - le32toh(h->tag_size)) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set tag: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if (EVP_DecryptFinal_ex(context, (uint8_t*) plaintext + plaintext_size, &added) != 1)
|
||||
if (EVP_DecryptFinal_ex(context, (uint8_t*) plaintext.iov_base + plaintext.iov_len, &added) != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Decryption failed (incorrect key?): %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
plaintext_size += added;
|
||||
plaintext.iov_len += added;
|
||||
|
||||
if (plaintext_size < ALIGN8(offsetof(struct metadata_credential_header, name)))
|
||||
if (plaintext.iov_len < ALIGN8(offsetof(struct metadata_credential_header, name)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Metadata header incomplete.");
|
||||
|
||||
m = plaintext;
|
||||
m = plaintext.iov_base;
|
||||
|
||||
if (le64toh(m->timestamp) != USEC_INFINITY &&
|
||||
le64toh(m->not_after) != USEC_INFINITY &&
|
||||
@@ -1332,7 +1305,7 @@ int decrypt_credential_and_warn(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Embedded credential name too long, refusing.");
|
||||
|
||||
hs = ALIGN8(offsetof(struct metadata_credential_header, name) + le32toh(m->name_size));
|
||||
if (plaintext_size < hs)
|
||||
if (plaintext.iov_len < hs)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Metadata header incomplete.");
|
||||
|
||||
if (le32toh(m->name_size) > 0) {
|
||||
@@ -1374,32 +1347,30 @@ int decrypt_credential_and_warn(
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
char *without_metadata;
|
||||
_cleanup_(iovec_done_erase) struct iovec without_metadata = {};
|
||||
|
||||
without_metadata = memdup_suffix0((uint8_t*) plaintext + hs, plaintext_size - hs);
|
||||
if (!without_metadata)
|
||||
without_metadata.iov_len = plaintext.iov_len - hs;
|
||||
without_metadata.iov_base = memdup_suffix0((uint8_t*) plaintext.iov_base + hs, without_metadata.iov_len);
|
||||
if (!without_metadata.iov_base)
|
||||
return log_oom();
|
||||
|
||||
*ret = without_metadata;
|
||||
*ret = TAKE_STRUCT(without_metadata);
|
||||
}
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = plaintext_size - hs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size) {
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
|
||||
}
|
||||
|
||||
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, const void *input, size_t input_size, void **ret, size_t *ret_size) {
|
||||
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, const struct iovec *input, struct iovec *ret) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
|
||||
}
|
||||
|
||||
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, const void *input, size_t input_size, void **ret, size_t *ret_size) {
|
||||
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, const struct iovec *input, struct iovec *ret) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ typedef enum CredentialSecretFlags {
|
||||
CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS = 1 << 2,
|
||||
} CredentialSecretFlags;
|
||||
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size);
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret);
|
||||
|
||||
int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed);
|
||||
|
||||
@@ -77,5 +77,5 @@ int get_credential_user_password(const char *username, char **ret_password, bool
|
||||
#define _CRED_AUTO SD_ID128_MAKE(a2,19,cb,07,85,b2,4c,04,b1,6d,18,ca,b9,d2,ee,01)
|
||||
#define _CRED_AUTO_INITRD SD_ID128_MAKE(02,dc,8e,de,3a,02,43,ab,a9,ec,54,9c,05,e6,a0,71)
|
||||
|
||||
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, const void *input, size_t input_size, void **ret, size_t *ret_size);
|
||||
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, const void *input, size_t input_size, void **ret, size_t *ret_size);
|
||||
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, const struct iovec *input, struct iovec *ret);
|
||||
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, const struct iovec *input, struct iovec *ret);
|
||||
|
||||
+100
-147
@@ -5067,28 +5067,22 @@ int tpm2_calculate_seal(
|
||||
TPM2_HANDLE parent_handle,
|
||||
const TPM2B_PUBLIC *parent_public,
|
||||
const TPMA_OBJECT *attributes,
|
||||
const void *secret,
|
||||
size_t secret_size,
|
||||
const struct iovec *secret,
|
||||
const TPM2B_DIGEST *policy,
|
||||
const char *pin,
|
||||
void **ret_secret,
|
||||
size_t *ret_secret_size,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_serialized_parent,
|
||||
size_t *ret_serialized_parent_size) {
|
||||
struct iovec *ret_secret,
|
||||
struct iovec *ret_blob,
|
||||
struct iovec *ret_serialized_parent) {
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
int r;
|
||||
|
||||
assert(parent_public);
|
||||
assert(secret || secret_size == 0);
|
||||
assert(iovec_is_valid(secret));
|
||||
assert(secret || ret_secret);
|
||||
assert(!(secret && ret_secret)); /* Either provide a secret, or we create one, but not both */
|
||||
assert(ret_blob);
|
||||
assert(ret_blob_size);
|
||||
assert(ret_serialized_parent);
|
||||
assert(ret_serialized_parent_size);
|
||||
|
||||
log_debug("Calculating sealed object.");
|
||||
|
||||
@@ -5109,27 +5103,27 @@ int tpm2_calculate_seal(
|
||||
parent_handle);
|
||||
}
|
||||
|
||||
_cleanup_(erase_and_freep) void *generated_secret = NULL;
|
||||
_cleanup_(iovec_done_erase) struct iovec generated_secret = {};
|
||||
if (!secret) {
|
||||
/* No secret provided, generate a random secret. We use SHA256 digest length, though it can
|
||||
* be up to TPM2_MAX_SEALED_DATA. The secret length is not limited to the nameAlg hash
|
||||
* size. */
|
||||
secret_size = TPM2_SHA256_DIGEST_SIZE;
|
||||
generated_secret = malloc(secret_size);
|
||||
if (!generated_secret)
|
||||
generated_secret.iov_len = TPM2_SHA256_DIGEST_SIZE;
|
||||
generated_secret.iov_base = malloc(generated_secret.iov_len);
|
||||
if (!generated_secret.iov_base)
|
||||
return log_oom_debug();
|
||||
|
||||
r = crypto_random_bytes(generated_secret, secret_size);
|
||||
r = crypto_random_bytes(generated_secret.iov_base, generated_secret.iov_len);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to generate secret key: %m");
|
||||
|
||||
secret = generated_secret;
|
||||
secret = &generated_secret;
|
||||
}
|
||||
|
||||
if (secret_size > TPM2_MAX_SEALED_DATA)
|
||||
if (secret->iov_len > TPM2_MAX_SEALED_DATA)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOVERFLOW),
|
||||
"Secret size %zu too large, limit is %d bytes.",
|
||||
secret_size, TPM2_MAX_SEALED_DATA);
|
||||
secret->iov_len, TPM2_MAX_SEALED_DATA);
|
||||
|
||||
TPM2B_DIGEST random_seed;
|
||||
TPM2B_ENCRYPTED_SECRET seed;
|
||||
@@ -5138,7 +5132,7 @@ int tpm2_calculate_seal(
|
||||
return r;
|
||||
|
||||
TPM2B_PUBLIC public;
|
||||
r = tpm2_calculate_seal_public(parent_public, attributes, policy, &random_seed, secret, secret_size, &public);
|
||||
r = tpm2_calculate_seal_public(parent_public, attributes, policy, &random_seed, secret->iov_base, secret->iov_len, &public);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -5148,13 +5142,12 @@ int tpm2_calculate_seal(
|
||||
return r;
|
||||
|
||||
TPM2B_PRIVATE private;
|
||||
r = tpm2_calculate_seal_private(parent_public, &name, pin, &random_seed, secret, secret_size, &private);
|
||||
r = tpm2_calculate_seal_private(parent_public, &name, pin, &random_seed, secret->iov_base, secret->iov_len, &private);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ void *blob = NULL;
|
||||
size_t blob_size;
|
||||
r = tpm2_marshal_blob(&public, &private, &seed, &blob, &blob_size);
|
||||
_cleanup_(iovec_done) struct iovec blob = {};
|
||||
r = tpm2_marshal_blob(&public, &private, &seed, &blob.iov_base, &blob.iov_len);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not create sealed blob: %m");
|
||||
|
||||
@@ -5163,25 +5156,20 @@ int tpm2_calculate_seal(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ void *serialized_parent = NULL;
|
||||
size_t serialized_parent_size;
|
||||
_cleanup_(iovec_done) struct iovec serialized_parent = {};
|
||||
r = tpm2_calculate_serialize(
|
||||
parent_handle,
|
||||
&parent_name,
|
||||
parent_public,
|
||||
&serialized_parent,
|
||||
&serialized_parent_size);
|
||||
&serialized_parent.iov_base,
|
||||
&serialized_parent.iov_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_secret)
|
||||
*ret_secret = TAKE_PTR(generated_secret);
|
||||
if (ret_secret_size)
|
||||
*ret_secret_size = secret_size;
|
||||
*ret_blob = TAKE_PTR(blob);
|
||||
*ret_blob_size = blob_size;
|
||||
*ret_serialized_parent = TAKE_PTR(serialized_parent);
|
||||
*ret_serialized_parent_size = serialized_parent_size;
|
||||
*ret_secret = TAKE_STRUCT(generated_secret);
|
||||
*ret_blob = TAKE_STRUCT(blob);
|
||||
*ret_serialized_parent = TAKE_STRUCT(serialized_parent);
|
||||
|
||||
return 0;
|
||||
#else /* HAVE_OPENSSL */
|
||||
@@ -5193,21 +5181,16 @@ int tpm2_seal(Tpm2Context *c,
|
||||
uint32_t seal_key_handle,
|
||||
const TPM2B_DIGEST *policy,
|
||||
const char *pin,
|
||||
void **ret_secret,
|
||||
size_t *ret_secret_size,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
struct iovec *ret_secret,
|
||||
struct iovec *ret_blob,
|
||||
uint16_t *ret_primary_alg,
|
||||
void **ret_srk_buf,
|
||||
size_t *ret_srk_buf_size) {
|
||||
struct iovec *ret_srk) {
|
||||
|
||||
uint16_t primary_alg = 0;
|
||||
int r;
|
||||
|
||||
assert(ret_secret);
|
||||
assert(ret_secret_size);
|
||||
assert(ret_blob);
|
||||
assert(ret_blob_size);
|
||||
|
||||
/* So here's what we do here: we connect to the TPM2 chip. It persistently contains a "seed" key that
|
||||
* is randomized when the TPM2 is first initialized or reset and remains stable across boots. We
|
||||
@@ -5271,7 +5254,7 @@ int tpm2_seal(Tpm2Context *c,
|
||||
return log_debug_errno(r, "Failed to generate secret key: %m");
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
|
||||
if (ret_srk_buf) {
|
||||
if (ret_srk) {
|
||||
_cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
|
||||
|
||||
if (IN_SET(seal_key_handle, 0, TPM2_SRK_HANDLE)) {
|
||||
@@ -5309,7 +5292,7 @@ int tpm2_seal(Tpm2Context *c,
|
||||
if (seal_key_handle != 0)
|
||||
log_debug("Using primary alg sealing, but seal key handle also provided; ignoring seal key handle.");
|
||||
|
||||
/* TODO: force all callers to provide ret_srk_buf, so we can stop sealing with the legacy templates. */
|
||||
/* TODO: force all callers to provide ret_srk, so we can stop sealing with the legacy templates. */
|
||||
primary_alg = TPM2_ALG_ECC;
|
||||
|
||||
TPM2B_PUBLIC template = {
|
||||
@@ -5353,47 +5336,46 @@ int tpm2_seal(Tpm2Context *c,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(erase_and_freep) void *secret = NULL;
|
||||
secret = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
|
||||
if (!secret)
|
||||
_cleanup_(iovec_done_erase) struct iovec secret = {};
|
||||
secret.iov_base = memdup(hmac_sensitive.data.buffer, hmac_sensitive.data.size);
|
||||
if (!secret.iov_base)
|
||||
return log_oom_debug();
|
||||
secret.iov_len = hmac_sensitive.data.size;
|
||||
|
||||
log_debug("Marshalling private and public part of HMAC key.");
|
||||
|
||||
_cleanup_free_ void *blob = NULL;
|
||||
size_t blob_size = 0;
|
||||
r = tpm2_marshal_blob(public, private, /* seed= */ NULL, &blob, &blob_size);
|
||||
_cleanup_(iovec_done) struct iovec blob = {};
|
||||
r = tpm2_marshal_blob(public, private, /* seed= */ NULL, &blob.iov_base, &blob.iov_len);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not create sealed blob: %m");
|
||||
|
||||
if (DEBUG_LOGGING)
|
||||
log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
|
||||
|
||||
_cleanup_free_ void *srk_buf = NULL;
|
||||
size_t srk_buf_size = 0;
|
||||
if (ret_srk_buf) {
|
||||
if (ret_srk) {
|
||||
_cleanup_(iovec_done) struct iovec srk = {};
|
||||
_cleanup_(Esys_Freep) void *tmp = NULL;
|
||||
r = tpm2_serialize(c, primary_handle, &tmp, &srk_buf_size);
|
||||
size_t tmp_size;
|
||||
|
||||
r = tpm2_serialize(c, primary_handle, &tmp, &tmp_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* make a copy since we don't want the caller to understand that
|
||||
* ESYS allocated the pointer. It would make tracking what deallocator
|
||||
* to use for srk_buf in which context a PITA.
|
||||
* to use for srk in which context a PITA.
|
||||
*/
|
||||
srk_buf = memdup(tmp, srk_buf_size);
|
||||
if (!srk_buf)
|
||||
srk.iov_base = memdup(tmp, tmp_size);
|
||||
if (!srk.iov_base)
|
||||
return log_oom_debug();
|
||||
srk.iov_len = tmp_size;
|
||||
|
||||
*ret_srk_buf = TAKE_PTR(srk_buf);
|
||||
*ret_srk_buf_size = srk_buf_size;
|
||||
*ret_srk = TAKE_STRUCT(srk);
|
||||
}
|
||||
|
||||
*ret_secret = TAKE_PTR(secret);
|
||||
*ret_secret_size = hmac_sensitive.data.size;
|
||||
*ret_blob = TAKE_PTR(blob);
|
||||
*ret_blob_size = blob_size;
|
||||
*ret_secret = TAKE_STRUCT(secret);
|
||||
*ret_blob = TAKE_STRUCT(blob);
|
||||
|
||||
if (ret_primary_alg)
|
||||
*ret_primary_alg = primary_alg;
|
||||
@@ -5406,31 +5388,24 @@ int tpm2_seal(Tpm2Context *c,
|
||||
int tpm2_unseal(Tpm2Context *c,
|
||||
uint32_t hash_pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const void *pubkey,
|
||||
size_t pubkey_size,
|
||||
const struct iovec *pubkey,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
JsonVariant *signature,
|
||||
const char *pin,
|
||||
const Tpm2PCRLockPolicy *pcrlock_policy,
|
||||
uint16_t primary_alg,
|
||||
const void *blob,
|
||||
size_t blob_size,
|
||||
const void *known_policy_hash,
|
||||
size_t known_policy_hash_size,
|
||||
const void *srk_buf,
|
||||
size_t srk_buf_size,
|
||||
void **ret_secret,
|
||||
size_t *ret_secret_size) {
|
||||
const struct iovec *blob,
|
||||
const struct iovec *known_policy_hash,
|
||||
const struct iovec *srk,
|
||||
struct iovec *ret_secret) {
|
||||
|
||||
TSS2_RC rc;
|
||||
int r;
|
||||
|
||||
assert(blob);
|
||||
assert(blob_size > 0);
|
||||
assert(known_policy_hash_size == 0 || known_policy_hash);
|
||||
assert(pubkey_size == 0 || pubkey);
|
||||
assert(iovec_is_set(blob));
|
||||
assert(iovec_is_valid(known_policy_hash));
|
||||
assert(iovec_is_valid(pubkey));
|
||||
assert(ret_secret);
|
||||
assert(ret_secret_size);
|
||||
|
||||
assert(TPM2_PCR_MASK_VALID(hash_pcr_mask));
|
||||
assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
|
||||
@@ -5448,7 +5423,7 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
TPM2B_PUBLIC public;
|
||||
TPM2B_PRIVATE private;
|
||||
TPM2B_ENCRYPTED_SECRET seed = {};
|
||||
r = tpm2_unmarshal_blob(blob, blob_size, &public, &private, &seed);
|
||||
r = tpm2_unmarshal_blob(blob->iov_base, blob->iov_len, &public, &private, &seed);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not extract parts from blob: %m");
|
||||
|
||||
@@ -5461,8 +5436,8 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
|
||||
if (srk_buf) {
|
||||
r = tpm2_deserialize(c, srk_buf, srk_buf_size, &primary_handle);
|
||||
if (iovec_is_set(srk)) {
|
||||
r = tpm2_deserialize(c, srk->iov_base, srk->iov_len, &primary_handle);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (primary_alg != 0) {
|
||||
@@ -5518,14 +5493,13 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
return r;
|
||||
|
||||
TPM2B_PUBLIC pubkey_tpm2b;
|
||||
_cleanup_free_ void *fp = NULL;
|
||||
size_t fp_size = 0;
|
||||
if (pubkey) {
|
||||
r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &pubkey_tpm2b);
|
||||
_cleanup_(iovec_done) struct iovec fp = {};
|
||||
if (iovec_is_set(pubkey)) {
|
||||
r = tpm2_tpm2b_public_from_pem(pubkey->iov_base, pubkey->iov_len, &pubkey_tpm2b);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not create TPMT_PUBLIC: %m");
|
||||
|
||||
r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp, &fp_size);
|
||||
r = tpm2_tpm2b_public_to_fingerprint(&pubkey_tpm2b, &fp.iov_base, &fp.iov_len);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not get key fingerprint: %m");
|
||||
}
|
||||
@@ -5563,8 +5537,8 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
policy_session,
|
||||
hash_pcr_mask,
|
||||
pcr_bank,
|
||||
pubkey ? &pubkey_tpm2b : NULL,
|
||||
fp, fp_size,
|
||||
iovec_is_set(pubkey) ? &pubkey_tpm2b : NULL,
|
||||
fp.iov_base, fp.iov_len,
|
||||
pubkey_pcr_mask,
|
||||
signature,
|
||||
!!pin,
|
||||
@@ -5575,8 +5549,8 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
|
||||
/* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not
|
||||
* wait until the TPM2 tells us to go away. */
|
||||
if (known_policy_hash_size > 0 &&
|
||||
memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash, known_policy_hash_size) != 0)
|
||||
if (iovec_is_set(known_policy_hash) &&
|
||||
memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash->iov_base, known_policy_hash->iov_len) != 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"Current policy digest does not match stored policy digest, cancelling "
|
||||
"TPM2 authentication attempt.");
|
||||
@@ -5598,17 +5572,17 @@ int tpm2_unseal(Tpm2Context *c,
|
||||
log_debug("A PCR value changed during the TPM2 policy session, restarting HMAC key unsealing (%u tries left).", i);
|
||||
}
|
||||
|
||||
_cleanup_(erase_and_freep) char *secret = NULL;
|
||||
secret = memdup(unsealed->buffer, unsealed->size);
|
||||
_cleanup_(iovec_done_erase) struct iovec secret = {};
|
||||
secret.iov_base = memdup(unsealed->buffer, unsealed->size);
|
||||
explicit_bzero_safe(unsealed->buffer, unsealed->size);
|
||||
if (!secret)
|
||||
if (!secret.iov_base)
|
||||
return log_oom_debug();
|
||||
secret.iov_len = unsealed->size;
|
||||
|
||||
if (DEBUG_LOGGING)
|
||||
log_debug("Completed TPM2 key unsealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
|
||||
|
||||
*ret_secret = TAKE_PTR(secret);
|
||||
*ret_secret_size = unsealed->size;
|
||||
*ret_secret = TAKE_STRUCT(secret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6967,18 +6941,13 @@ int tpm2_make_luks2_json(
|
||||
int keyslot,
|
||||
uint32_t hash_pcr_mask,
|
||||
uint16_t pcr_bank,
|
||||
const void *pubkey,
|
||||
size_t pubkey_size,
|
||||
const struct iovec *pubkey,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
uint16_t primary_alg,
|
||||
const void *blob,
|
||||
size_t blob_size,
|
||||
const void *policy_hash,
|
||||
size_t policy_hash_size,
|
||||
const void *salt,
|
||||
size_t salt_size,
|
||||
const void *srk_buf,
|
||||
size_t srk_buf_size,
|
||||
const struct iovec *blob,
|
||||
const struct iovec *policy_hash,
|
||||
const struct iovec *salt,
|
||||
const struct iovec *srk,
|
||||
TPM2Flags flags,
|
||||
JsonVariant **ret) {
|
||||
|
||||
@@ -6986,9 +6955,9 @@ int tpm2_make_luks2_json(
|
||||
_cleanup_free_ char *keyslot_as_string = NULL;
|
||||
int r;
|
||||
|
||||
assert(blob || blob_size == 0);
|
||||
assert(policy_hash || policy_hash_size == 0);
|
||||
assert(pubkey || pubkey_size == 0);
|
||||
assert(iovec_is_valid(pubkey));
|
||||
assert(iovec_is_valid(blob));
|
||||
assert(iovec_is_valid(policy_hash));
|
||||
|
||||
if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
|
||||
return -ENOMEM;
|
||||
@@ -7011,17 +6980,17 @@ int tpm2_make_luks2_json(
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")),
|
||||
JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
|
||||
JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)),
|
||||
JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_IOVEC_BASE64(blob)),
|
||||
JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)),
|
||||
JSON_BUILD_PAIR_CONDITION(!!tpm2_hash_alg_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_hash_alg_to_string(pcr_bank))),
|
||||
JSON_BUILD_PAIR_CONDITION(!!tpm2_asym_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_asym_alg_to_string(primary_alg))),
|
||||
JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)),
|
||||
JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_IOVEC_HEX(policy_hash)),
|
||||
JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)),
|
||||
JSON_BUILD_PAIR("tpm2_pcrlock", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PCRLOCK)),
|
||||
JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)),
|
||||
JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)),
|
||||
JSON_BUILD_PAIR_CONDITION(salt, "tpm2_salt", JSON_BUILD_BASE64(salt, salt_size)),
|
||||
JSON_BUILD_PAIR_CONDITION(srk_buf, "tpm2_srk", JSON_BUILD_BASE64(srk_buf, srk_buf_size))));
|
||||
JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_IOVEC_BASE64(pubkey)),
|
||||
JSON_BUILD_PAIR_CONDITION(iovec_is_set(salt), "tpm2_salt", JSON_BUILD_IOVEC_BASE64(salt)),
|
||||
JSON_BUILD_PAIR_CONDITION(iovec_is_set(srk), "tpm2_srk", JSON_BUILD_IOVEC_BASE64(srk))));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -7036,22 +7005,16 @@ int tpm2_parse_luks2_json(
|
||||
int *ret_keyslot,
|
||||
uint32_t *ret_hash_pcr_mask,
|
||||
uint16_t *ret_pcr_bank,
|
||||
void **ret_pubkey,
|
||||
size_t *ret_pubkey_size,
|
||||
struct iovec *ret_pubkey,
|
||||
uint32_t *ret_pubkey_pcr_mask,
|
||||
uint16_t *ret_primary_alg,
|
||||
void **ret_blob,
|
||||
size_t *ret_blob_size,
|
||||
void **ret_policy_hash,
|
||||
size_t *ret_policy_hash_size,
|
||||
void **ret_salt,
|
||||
size_t *ret_salt_size,
|
||||
void **ret_srk_buf,
|
||||
size_t *ret_srk_buf_size,
|
||||
struct iovec *ret_blob,
|
||||
struct iovec *ret_policy_hash,
|
||||
struct iovec *ret_salt,
|
||||
struct iovec *ret_srk,
|
||||
TPM2Flags *ret_flags) {
|
||||
|
||||
_cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
|
||||
size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
|
||||
_cleanup_(iovec_done) struct iovec blob = {}, policy_hash = {}, pubkey = {}, salt = {}, srk = {};
|
||||
uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
|
||||
uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
|
||||
uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
|
||||
@@ -7116,7 +7079,7 @@ int tpm2_parse_luks2_json(
|
||||
if (!w)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
|
||||
|
||||
r = json_variant_unbase64(w, &blob, &blob_size);
|
||||
r = json_variant_unbase64_iovec(w, &blob);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
|
||||
|
||||
@@ -7124,7 +7087,7 @@ int tpm2_parse_luks2_json(
|
||||
if (!w)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
|
||||
|
||||
r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
|
||||
r = json_variant_unhex_iovec(w, &policy_hash);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
|
||||
|
||||
@@ -7146,7 +7109,7 @@ int tpm2_parse_luks2_json(
|
||||
|
||||
w = json_variant_by_key(v, "tpm2_salt");
|
||||
if (w) {
|
||||
r = json_variant_unbase64(w, &salt, &salt_size);
|
||||
r = json_variant_unbase64_iovec(w, &salt);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Invalid base64 data in 'tpm2_salt' field.");
|
||||
}
|
||||
@@ -7160,7 +7123,7 @@ int tpm2_parse_luks2_json(
|
||||
|
||||
w = json_variant_by_key(v, "tpm2_pubkey");
|
||||
if (w) {
|
||||
r = json_variant_unbase64(w, &pubkey, &pubkey_size);
|
||||
r = json_variant_unbase64_iovec(w, &pubkey);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to decode PCR public key.");
|
||||
} else if (pubkey_pcr_mask != 0)
|
||||
@@ -7168,7 +7131,7 @@ int tpm2_parse_luks2_json(
|
||||
|
||||
w = json_variant_by_key(v, "tpm2_srk");
|
||||
if (w) {
|
||||
r = json_variant_unbase64(w, &srk_buf, &srk_buf_size);
|
||||
r = json_variant_unbase64_iovec(w, &srk);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Invalid base64 data in 'tpm2_srk' field.");
|
||||
}
|
||||
@@ -7180,31 +7143,21 @@ int tpm2_parse_luks2_json(
|
||||
if (ret_pcr_bank)
|
||||
*ret_pcr_bank = pcr_bank;
|
||||
if (ret_pubkey)
|
||||
*ret_pubkey = TAKE_PTR(pubkey);
|
||||
if (ret_pubkey_size)
|
||||
*ret_pubkey_size = pubkey_size;
|
||||
*ret_pubkey = TAKE_STRUCT(pubkey);
|
||||
if (ret_pubkey_pcr_mask)
|
||||
*ret_pubkey_pcr_mask = pubkey_pcr_mask;
|
||||
if (ret_primary_alg)
|
||||
*ret_primary_alg = primary_alg;
|
||||
if (ret_blob)
|
||||
*ret_blob = TAKE_PTR(blob);
|
||||
if (ret_blob_size)
|
||||
*ret_blob_size = blob_size;
|
||||
*ret_blob = TAKE_STRUCT(blob);
|
||||
if (ret_policy_hash)
|
||||
*ret_policy_hash = TAKE_PTR(policy_hash);
|
||||
if (ret_policy_hash_size)
|
||||
*ret_policy_hash_size = policy_hash_size;
|
||||
*ret_policy_hash = TAKE_STRUCT(policy_hash);
|
||||
if (ret_salt)
|
||||
*ret_salt = TAKE_PTR(salt);
|
||||
if (ret_salt_size)
|
||||
*ret_salt_size = salt_size;
|
||||
*ret_salt = TAKE_STRUCT(salt);
|
||||
if (ret_flags)
|
||||
*ret_flags = flags;
|
||||
if (ret_srk_buf)
|
||||
*ret_srk_buf = TAKE_PTR(srk_buf);
|
||||
if (ret_srk_buf_size)
|
||||
*ret_srk_buf_size = srk_buf_size;
|
||||
if (ret_srk)
|
||||
*ret_srk = TAKE_STRUCT(srk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TP
|
||||
int tpm2_calculate_policy_super_pcr(Tpm2PCRPrediction *prediction, uint16_t algorithm, TPM2B_DIGEST *pcr_policy);
|
||||
int tpm2_calculate_serialize(TPM2_HANDLE handle, const TPM2B_NAME *name, const TPM2B_PUBLIC *public, void **ret_serialized, size_t *ret_serialized_size);
|
||||
int tpm2_calculate_sealing_policy(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, const TPM2B_PUBLIC *public, bool use_pin, const Tpm2PCRLockPolicy *policy, TPM2B_DIGEST *digest);
|
||||
int tpm2_calculate_seal(TPM2_HANDLE parent_handle, const TPM2B_PUBLIC *parent_public, const TPMA_OBJECT *attributes, const void *secret, size_t secret_size, const TPM2B_DIGEST *policy, const char *pin, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, void **ret_serialized_parent, size_t *ret_serialized_parent_size);
|
||||
int tpm2_calculate_seal(TPM2_HANDLE parent_handle, const TPM2B_PUBLIC *parent_public, const TPMA_OBJECT *attributes, const struct iovec *secret, const TPM2B_DIGEST *policy, const char *pin, struct iovec *ret_secret, struct iovec *ret_blob, struct iovec *ret_serialized_parent);
|
||||
|
||||
int tpm2_get_srk_template(TPMI_ALG_PUBLIC alg, TPMT_PUBLIC *ret_template);
|
||||
int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template);
|
||||
@@ -285,8 +285,8 @@ int tpm2_get_best_srk_template(Tpm2Context *c, TPMT_PUBLIC *ret_template);
|
||||
int tpm2_get_srk(Tpm2Context *c, const Tpm2Handle *session, TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle);
|
||||
int tpm2_get_or_create_srk(Tpm2Context *c, const Tpm2Handle *session, TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle);
|
||||
|
||||
int tpm2_seal(Tpm2Context *c, uint32_t seal_key_handle, const TPM2B_DIGEST *policy, const char *pin, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, uint16_t *ret_primary_alg, void **ret_srk_buf, size_t *ret_srk_buf_size);
|
||||
int tpm2_unseal(Tpm2Context *c, 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, const Tpm2PCRLockPolicy *pcrlock_policy, 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);
|
||||
int tpm2_seal(Tpm2Context *c, uint32_t seal_key_handle, const TPM2B_DIGEST *policy, const char *pin, struct iovec *ret_secret, struct iovec *ret_blob, uint16_t *ret_primary_alg, struct iovec *ret_srk);
|
||||
int tpm2_unseal(Tpm2Context *c, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, JsonVariant *signature, const char *pin, const Tpm2PCRLockPolicy *pcrlock_policy, uint16_t primary_alg, const struct iovec *blob, const struct iovec *policy_hash, const struct iovec *srk, struct iovec *ret_secret);
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret);
|
||||
@@ -383,8 +383,8 @@ int tpm2_find_device_auto(char **ret);
|
||||
int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret);
|
||||
int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret);
|
||||
|
||||
int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, const void *salt, size_t salt_size, const void *srk_buf, size_t srk_buf_size, TPM2Flags flags, JsonVariant **ret);
|
||||
int tpm2_parse_luks2_json(JsonVariant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, void **ret_pubkey, size_t *ret_pubkey_size, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, void **ret_blob, size_t *ret_blob_size, void **ret_policy_hash, size_t *ret_policy_hash_size, void **ret_salt, size_t *ret_salt_size, void **ret_srk_buf, size_t *ret_srk_buf_size, TPM2Flags *ret_flags);
|
||||
int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const struct iovec *blob, const struct iovec *policy_hash, const struct iovec *salt, const struct iovec *srk, TPM2Flags flags, JsonVariant **ret);
|
||||
int tpm2_parse_luks2_json(JsonVariant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, struct iovec *ret_pubkey, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, struct iovec *ret_blob, struct iovec *ret_policy_hash, struct iovec *ret_salt, struct iovec *ret_srk, TPM2Flags *ret_flags);
|
||||
|
||||
/* Default to PCR 7 only */
|
||||
#define TPM2_PCR_INDEX_DEFAULT UINT32_C(7)
|
||||
|
||||
Reference in New Issue
Block a user