]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2-util: more iovec'ification 30754/head
authorLennart Poettering <lennart@poettering.net>
Mon, 20 Nov 2023 16:18:43 +0000 (17:18 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 5 Jan 2024 10:34:46 +0000 (11:34 +0100)
Let's move more code to using struct iovec for passing around binary
chunks of data.

No real changes in behaviour, just refactoring.

15 files changed:
src/core/exec-credential.c
src/creds/creds.c
src/cryptenroll/cryptenroll-tpm2.c
src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h
src/cryptsetup/cryptsetup-tpm2.c
src/cryptsetup/cryptsetup-tpm2.h
src/cryptsetup/cryptsetup.c
src/partition/repart.c
src/shared/creds-util.c
src/shared/creds-util.h
src/shared/tpm2-util.c
src/shared/tpm2-util.h
src/test/test-tpm2.c

index 6bcfb68d8f21644b63da2dc700b9c184e03f4ab0..513087d06925bdc0024ed8ace033f2dca39a739c 100644 (file)
@@ -9,6 +9,7 @@
 #include "fileio.h"
 #include "glob-util.h"
 #include "io-util.h"
+#include "iovec-util.h"
 #include "label-util.h"
 #include "mkdir-label.h"
 #include "mount-util.h"
@@ -271,20 +272,23 @@ static int maybe_decrypt_and_write_credential(
                 size_t size,
                 uint64_t *left) {
 
-        _cleanup_free_ void *plaintext = NULL;
+        _cleanup_(iovec_done_erase) struct iovec plaintext = {};
         size_t add;
         int r;
 
         if (encrypted) {
-                size_t plaintext_size = 0;
-
-                r = decrypt_credential_and_warn(id, now(CLOCK_REALTIME), NULL, NULL, data, size,
-                                                &plaintext, &plaintext_size);
+                r = decrypt_credential_and_warn(
+                                id,
+                                now(CLOCK_REALTIME),
+                                /* tpm2_device= */ NULL,
+                                /* tpm2_signature_path= */ NULL,
+                                &IOVEC_MAKE(data, size),
+                                &plaintext);
                 if (r < 0)
                         return r;
 
-                data = plaintext;
-                size = plaintext_size;
+                data = plaintext.iov_base;
+                size = plaintext.iov_len;
         }
 
         add = strlen(id) + size;
@@ -684,7 +688,7 @@ static int acquire_credentials(
         /* Finally, we add in literally specified credentials. If the credentials already exist, we'll not
          * add them, so that they can act as a "default" if the same credential is specified multiple times. */
         HASHMAP_FOREACH(sc, context->set_credentials) {
-                _cleanup_(erase_and_freep) void *plaintext = NULL;
+                _cleanup_(iovec_done_erase) struct iovec plaintext = {};
                 const char *data;
                 size_t size, add;
 
@@ -698,11 +702,18 @@ static int acquire_credentials(
                         return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sc->id);
 
                 if (sc->encrypted) {
-                        r = decrypt_credential_and_warn(sc->id, now(CLOCK_REALTIME), NULL, NULL, sc->data, sc->size, &plaintext, &size);
+                        r = decrypt_credential_and_warn(
+                                        sc->id,
+                                        now(CLOCK_REALTIME),
+                                        /* tpm2_device= */ NULL,
+                                        /* tpm2_signature_path= */ NULL,
+                                        &IOVEC_MAKE(sc->data, sc->size),
+                                        &plaintext);
                         if (r < 0)
                                 return r;
 
-                        data = plaintext;
+                        data = plaintext.iov_base;
+                        size = plaintext.iov_len;
                 } else {
                         data = sc->data;
                         size = sc->size;
index f84eee292bec178d80e9191f964dbd17ad88c678..01b2844dd301a873334b346859627580aac296bd 100644 (file)
@@ -421,22 +421,21 @@ static int verb_cat(int argc, char **argv, void *userdata) {
                 }
 
                 if (encrypted) {
-                        _cleanup_(erase_and_freep) void *plaintext = NULL;
-                        size_t plaintext_size;
+                        _cleanup_(iovec_done_erase) struct iovec plaintext = {};
 
                         r = decrypt_credential_and_warn(
                                         *cn,
                                         timestamp,
                                         arg_tpm2_device,
                                         arg_tpm2_signature,
-                                        data, size,
-                                        &plaintext, &plaintext_size);
+                                        &IOVEC_MAKE(data, size),
+                                        &plaintext);
                         if (r < 0)
                                 return r;
 
                         erase_and_free(data);
-                        data = TAKE_PTR(plaintext);
-                        size = plaintext_size;
+                        data = TAKE_PTR(plaintext.iov_base);
+                        size = plaintext.iov_len;
                 }
 
                 r = write_blob(stdout, data, size);
@@ -448,11 +447,9 @@ static int verb_cat(int argc, char **argv, void *userdata) {
 }
 
 static int verb_encrypt(int argc, char **argv, void *userdata) {
+        _cleanup_(iovec_done_erase) struct iovec plaintext = {}, output = {};
         _cleanup_free_ char *base64_buf = NULL, *fname = NULL;
-        _cleanup_(erase_and_freep) char *plaintext = NULL;
         const char *input_path, *output_path, *name;
-        _cleanup_free_ void *output = NULL;
-        size_t plaintext_size, output_size;
         ssize_t base64_size;
         usec_t timestamp;
         int r;
@@ -462,9 +459,9 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
         input_path = empty_or_dash(argv[1]) ? NULL : argv[1];
 
         if (input_path)
-                r = read_full_file_full(AT_FDCWD, input_path, UINT64_MAX, CREDENTIAL_SIZE_MAX, READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &plaintext, &plaintext_size);
+                r = read_full_file_full(AT_FDCWD, input_path, UINT64_MAX, CREDENTIAL_SIZE_MAX, READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, (char**) &plaintext.iov_base, &plaintext.iov_len);
         else
-                r = read_full_stream_full(stdin, NULL, UINT64_MAX, CREDENTIAL_SIZE_MAX, READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER, &plaintext, &plaintext_size);
+                r = read_full_stream_full(stdin, NULL, UINT64_MAX, CREDENTIAL_SIZE_MAX, READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER, (char**) &plaintext.iov_base, &plaintext.iov_len);
         if (r == -E2BIG)
                 return log_error_errno(r, "Plaintext too long for credential (allowed size: %zu).", (size_t) CREDENTIAL_SIZE_MAX);
         if (r < 0)
@@ -503,12 +500,12 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
                         arg_tpm2_pcr_mask,
                         arg_tpm2_public_key,
                         arg_tpm2_public_key_pcr_mask,
-                        plaintext, plaintext_size,
-                        &output, &output_size);
+                        &plaintext,
+                        &output);
         if (r < 0)
                 return r;
 
-        base64_size = base64mem_full(output, output_size, arg_pretty ? 69 : 79, &base64_buf);
+        base64_size = base64mem_full(output.iov_base, output.iov_len, arg_pretty ? 69 : 79, &base64_buf);
         if (base64_size < 0)
                 return base64_size;
 
@@ -544,11 +541,10 @@ static int verb_encrypt(int argc, char **argv, void *userdata) {
 }
 
 static int verb_decrypt(int argc, char **argv, void *userdata) {
-        _cleanup_(erase_and_freep) void *plaintext = NULL;
-        _cleanup_free_ char *input = NULL, *fname = NULL;
+        _cleanup_(iovec_done_erase) struct iovec input = {}, plaintext = {};
+        _cleanup_free_ char *fname = NULL;
         _cleanup_fclose_ FILE *output_file = NULL;
         const char *input_path, *output_path, *name;
-        size_t input_size, plaintext_size;
         usec_t timestamp;
         FILE *f;
         int r;
@@ -558,9 +554,9 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
         input_path = empty_or_dash(argv[1]) ? NULL : argv[1];
 
         if (input_path)
-                r = read_full_file_full(AT_FDCWD, argv[1], UINT64_MAX, CREDENTIAL_ENCRYPTED_SIZE_MAX, READ_FULL_FILE_UNBASE64|READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &input, &input_size);
+                r = read_full_file_full(AT_FDCWD, argv[1], UINT64_MAX, CREDENTIAL_ENCRYPTED_SIZE_MAX, READ_FULL_FILE_UNBASE64|READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, (char**) &input, &input.iov_len);
         else
-                r = read_full_stream_full(stdin, NULL, UINT64_MAX, CREDENTIAL_ENCRYPTED_SIZE_MAX, READ_FULL_FILE_UNBASE64|READ_FULL_FILE_FAIL_WHEN_LARGER, &input, &input_size);
+                r = read_full_stream_full(stdin, NULL, UINT64_MAX, CREDENTIAL_ENCRYPTED_SIZE_MAX, READ_FULL_FILE_UNBASE64|READ_FULL_FILE_FAIL_WHEN_LARGER, (char**) &input, &input.iov_len);
         if (r == -E2BIG)
                 return log_error_errno(r, "Data too long for encrypted credential (allowed size: %zu).", (size_t) CREDENTIAL_ENCRYPTED_SIZE_MAX);
         if (r < 0)
@@ -592,8 +588,8 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
                         timestamp,
                         arg_tpm2_device,
                         arg_tpm2_signature,
-                        input, input_size,
-                        &plaintext, &plaintext_size);
+                        &input,
+                        &plaintext);
         if (r < 0)
                 return r;
 
@@ -606,7 +602,7 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
         } else
                 f = stdout;
 
-        r = write_blob(f, plaintext, plaintext_size);
+        r = write_blob(f, plaintext.iov_base, plaintext.iov_len);
         if (r < 0)
                 return r;
 
@@ -614,14 +610,14 @@ static int verb_decrypt(int argc, char **argv, void *userdata) {
 }
 
 static int verb_setup(int argc, char **argv, void *userdata) {
-        size_t size;
+        _cleanup_(iovec_done_erase) struct iovec host_key = {};
         int r;
 
-        r = get_credential_host_secret(CREDENTIAL_SECRET_GENERATE|CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED, NULL, &size);
+        r = get_credential_host_secret(CREDENTIAL_SECRET_GENERATE|CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED, &host_key);
         if (r < 0)
                 return log_error_errno(r, "Failed to setup credentials host key: %m");
 
-        log_info("%zu byte credentials host key set up.", size);
+        log_info("%zu byte credentials host key set up.", host_key.iov_len);
 
         return EXIT_SUCCESS;
 }
@@ -1032,8 +1028,8 @@ static int vl_method_encrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
                         arg_tpm2_pcr_mask,
                         arg_tpm2_public_key,
                         arg_tpm2_public_key_pcr_mask,
-                        p.text ?: p.data.iov_base, p.text ? strlen(p.text) : p.data.iov_len,
-                        &output.iov_base, &output.iov_len);
+                        p.text ? &IOVEC_MAKE_STRING(p.text) : &p.data,
+                        &output);
         if (r < 0)
                 return r;
 
@@ -1106,8 +1102,8 @@ static int vl_method_decrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
                         p.timestamp,
                         arg_tpm2_device,
                         arg_tpm2_signature,
-                        p.blob.iov_base, p.blob.iov_len,
-                        &output.iov_base, &output.iov_len);
+                        &p.blob,
+                        &output);
         if (r == -EBADMSG)
                 return varlink_error(link, "io.systemd.Credentials.BadFormat", NULL);
         if (r == -EREMOTE)
index 0268d8f7721d83bdf02e6573f263fa5dd7fd858f..608b94ea78027c6c2d1849a59e044d07986511bf 100644 (file)
@@ -143,12 +143,10 @@ int enroll_tpm2(struct crypt_device *cd,
                 bool use_pin,
                 const char *pcrlock_path) {
 
-        _cleanup_(erase_and_freep) void *secret = NULL;
         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL;
         _cleanup_(erase_and_freep) char *base64_encoded = NULL;
-        _cleanup_free_ void *srk_buf = NULL;
-        size_t secret_size, blob_size, pubkey_size = 0, srk_buf_size = 0;
-        _cleanup_free_ void *blob = NULL, *pubkey = NULL;
+        _cleanup_(iovec_done) struct iovec srk = {}, blob = {}, pubkey = {};
+        _cleanup_(iovec_done_erase) struct iovec secret = {};
         const char *node;
         _cleanup_(erase_and_freep) char *pin_str = NULL;
         ssize_t base64_encoded_size;
@@ -194,7 +192,7 @@ int enroll_tpm2(struct crypt_device *cd,
         }
 
         TPM2B_PUBLIC public = {};
-        r = tpm2_load_pcr_public_key(pubkey_path, &pubkey, &pubkey_size);
+        r = tpm2_load_pcr_public_key(pubkey_path, &pubkey.iov_base, &pubkey.iov_len);
         if (r < 0) {
                 if (pubkey_path || signature_path || r != -ENOENT)
                         return log_error_errno(r, "Failed to read TPM PCR public key: %m");
@@ -202,7 +200,7 @@ int enroll_tpm2(struct crypt_device *cd,
                 log_debug_errno(r, "Failed to read TPM2 PCR public key, proceeding without: %m");
                 pubkey_pcr_mask = 0;
         } else {
-                r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &public);
+                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");
 
@@ -271,7 +269,7 @@ int enroll_tpm2(struct crypt_device *cd,
         r = tpm2_calculate_sealing_policy(
                         hash_pcr_values,
                         n_hash_pcr_values,
-                        pubkey ? &public : NULL,
+                        iovec_is_set(&pubkey) ? &public : NULL,
                         use_pin,
                         pcrlock_path ? &pcrlock_policy : NULL,
                         &policy);
@@ -283,21 +281,21 @@ int enroll_tpm2(struct crypt_device *cd,
                                 seal_key_handle,
                                 &device_key_public,
                                 /* attributes= */ NULL,
-                                /* secret= */ NULL, /* secret_size= */ 0,
+                                /* secret= */ NULL,
                                 &policy,
                                 pin_str,
-                                &secret, &secret_size,
-                                &blob, &blob_size,
-                                &srk_buf, &srk_buf_size);
+                                &secret,
+                                &blob,
+                                &srk);
         else
                 r = tpm2_seal(tpm2_context,
                               seal_key_handle,
                               &policy,
                               pin_str,
-                              &secret, &secret_size,
-                              &blob, &blob_size,
+                              &secret,
+                              &blob,
                               /* ret_primary_alg= */ NULL,
-                              &srk_buf, &srk_buf_size);
+                              &srk);
         if (r < 0)
                 return log_error_errno(r, "Failed to seal to TPM2: %m");
 
@@ -313,33 +311,32 @@ int enroll_tpm2(struct crypt_device *cd,
         }
 
         /* If possible, verify the sealed data object. */
-        if ((!pubkey || signature_json) && !any_pcr_value_specified && !device_key) {
-                _cleanup_(erase_and_freep) void *secret2 = NULL;
-                size_t secret2_size;
+        if ((!iovec_is_set(&pubkey) || signature_json) && !any_pcr_value_specified && !device_key) {
+                _cleanup_(iovec_done_erase) struct iovec secret2 = {};
 
                 log_debug("Unsealing for verification...");
                 r = tpm2_unseal(tpm2_context,
                                 hash_pcr_mask,
                                 hash_pcr_bank,
-                                pubkey, pubkey_size,
+                                &pubkey,
                                 pubkey_pcr_mask,
                                 signature_json,
                                 pin_str,
                                 pcrlock_path ? &pcrlock_policy : NULL,
                                 /* primary_alg= */ 0,
-                                blob, blob_size,
-                                policy.buffer, policy.size,
-                                srk_buf, srk_buf_size,
-                                &secret2, &secret2_size);
+                                &blob,
+                                &IOVEC_MAKE(policy.buffer, policy.size),
+                                &srk,
+                                &secret2);
                 if (r < 0)
                         return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
-                if (memcmp_nn(secret, secret_size, secret2, secret2_size) != 0)
+                if (iovec_memcmp(&secret, &secret2) != 0)
                         return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 seal/unseal verification failed.");
         }
 
         /* let's base64 encode the key to use, for compat with homed (and it's easier to every type it in by keyboard, if that might end up being necessary. */
-        base64_encoded_size = base64mem(secret, secret_size, &base64_encoded);
+        base64_encoded_size = base64mem(secret.iov_base, secret.iov_len, &base64_encoded);
         if (base64_encoded_size < 0)
                 return log_error_errno(base64_encoded_size, "Failed to base64 encode secret key: %m");
 
@@ -361,14 +358,13 @@ int enroll_tpm2(struct crypt_device *cd,
                         keyslot,
                         hash_pcr_mask,
                         hash_pcr_bank,
-                        pubkey, pubkey_size,
+                        &pubkey,
                         pubkey_pcr_mask,
                         /* primary_alg= */ 0,
-                        blob, blob_size,
-                        policy.buffer, policy.size,
-                        use_pin ? binary_salt : NULL,
-                        use_pin ? sizeof(binary_salt) : 0,
-                        srk_buf, srk_buf_size,
+                        &blob,
+                        &IOVEC_MAKE(policy.buffer, policy.size),
+                        use_pin ? &IOVEC_MAKE(binary_salt, sizeof(binary_salt)) : NULL,
+                        &srk,
                         flags,
                         &v);
         if (r < 0)
index 6fee8319a7f0bb0b11e1fed3d3cacdc036d2f05c..29cc1ac5430fb322a97955ba9239984eeeb1b6b7 100644 (file)
@@ -42,9 +42,8 @@ _public_ int cryptsetup_token_open_pin(
                 void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) {
 
         _cleanup_(erase_and_freep) char *base64_encoded = NULL, *pin_string = NULL;
-        _cleanup_free_ void *blob = NULL, *pubkey = NULL, *policy_hash = NULL, *salt = NULL, *srk_buf = NULL;
-        size_t blob_size, policy_hash_size, decrypted_key_size, pubkey_size, salt_size = 0, srk_buf_size = 0;
-        _cleanup_(erase_and_freep) void *decrypted_key = NULL;
+        _cleanup_(iovec_done) struct iovec blob = {}, pubkey = {}, policy_hash = {}, salt = {}, srk = {};
+        _cleanup_(iovec_done_erase) struct iovec decrypted_key = {};
         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
         uint32_t hash_pcr_mask, pubkey_pcr_mask;
         systemd_tpm2_plugin_params params = {
@@ -79,21 +78,16 @@ _public_ int cryptsetup_token_open_pin(
 
         r = tpm2_parse_luks2_json(
                         v,
-                        NULL,
+                        /* ret_keyslot= */ NULL,
                         &hash_pcr_mask,
                         &pcr_bank,
                         &pubkey,
-                        &pubkey_size,
                         &pubkey_pcr_mask,
                         &primary_alg,
                         &blob,
-                        &blob_size,
                         &policy_hash,
-                        &policy_hash_size,
                         &salt,
-                        &salt_size,
-                        &srk_buf,
-                        &srk_buf_size,
+                        &srk,
                         &flags);
         if (r < 0)
                 return log_debug_open_error(cd, r);
@@ -105,28 +99,23 @@ _public_ int cryptsetup_token_open_pin(
                         params.device,
                         hash_pcr_mask,
                         pcr_bank,
-                        pubkey, pubkey_size,
+                        &pubkey,
                         pubkey_pcr_mask,
                         params.signature_path,
                         pin_string,
                         params.pcrlock_path,
                         primary_alg,
-                        blob,
-                        blob_size,
-                        policy_hash,
-                        policy_hash_size,
-                        salt,
-                        salt_size,
-                        srk_buf,
-                        srk_buf_size,
+                        &blob,
+                        &policy_hash,
+                        &salt,
+                        &srk,
                         flags,
-                        &decrypted_key,
-                        &decrypted_key_size);
+                        &decrypted_key);
         if (r < 0)
                 return log_debug_open_error(cd, r);
 
         /* Before using this key as passphrase we base64 encode it, for compat with homed */
-        base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+        base64_encoded_size = base64mem(decrypted_key.iov_base, decrypted_key.iov_len, &base64_encoded);
         if (base64_encoded_size < 0)
                 return log_debug_open_error(cd, base64_encoded_size);
 
@@ -177,9 +166,8 @@ _public_ void cryptsetup_token_dump(
                 const char *json /* validated 'systemd-tpm2' token if cryptsetup_token_validate is defined */) {
 
         _cleanup_free_ char *hash_pcrs_str = NULL, *pubkey_pcrs_str = NULL, *blob_str = NULL, *policy_hash_str = NULL, *pubkey_str = NULL;
-        _cleanup_free_ void *blob = NULL, *pubkey = NULL, *policy_hash = NULL, *salt = NULL, *srk_buf = NULL;
+        _cleanup_(iovec_done) struct iovec blob = {}, pubkey = {}, policy_hash = {}, salt = {}, srk = {};
         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-        size_t blob_size, policy_hash_size, pubkey_size, salt_size = 0, srk_buf_size = 0;
         uint32_t hash_pcr_mask, pubkey_pcr_mask;
         uint16_t pcr_bank, primary_alg;
         TPM2Flags flags = 0;
@@ -197,17 +185,12 @@ _public_ void cryptsetup_token_dump(
                         &hash_pcr_mask,
                         &pcr_bank,
                         &pubkey,
-                        &pubkey_size,
                         &pubkey_pcr_mask,
                         &primary_alg,
                         &blob,
-                        &blob_size,
                         &policy_hash,
-                        &policy_hash_size,
                         &salt,
-                        &salt_size,
-                        &srk_buf,
-                        &srk_buf_size,
+                        &srk,
                         &flags);
         if (r < 0)
                 return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " JSON fields: %m");
@@ -220,15 +203,15 @@ _public_ void cryptsetup_token_dump(
         if (!pubkey_pcrs_str)
                 return (void) crypt_log_debug_errno(cd, ENOMEM, "Cannot format PCR hash mask: %m");
 
-        r = crypt_dump_buffer_to_hex_string(blob, blob_size, &blob_str);
+        r = crypt_dump_buffer_to_hex_string(blob.iov_base, blob.iov_len, &blob_str);
         if (r < 0)
                 return (void) crypt_log_debug_errno(cd, r, "Cannot dump " TOKEN_NAME " content: %m");
 
-        r = crypt_dump_buffer_to_hex_string(pubkey, pubkey_size, &pubkey_str);
+        r = crypt_dump_buffer_to_hex_string(pubkey.iov_base, pubkey.iov_len, &pubkey_str);
         if (r < 0)
                 return (void) crypt_log_debug_errno(cd, r, "Cannot dump " TOKEN_NAME " content: %m");
 
-        r = crypt_dump_buffer_to_hex_string(policy_hash, policy_hash_size, &policy_hash_str);
+        r = crypt_dump_buffer_to_hex_string(policy_hash.iov_base, policy_hash.iov_len, &policy_hash_str);
         if (r < 0)
                 return (void) crypt_log_debug_errno(cd, r, "Cannot dump " TOKEN_NAME " content: %m");
 
@@ -241,8 +224,8 @@ _public_ void cryptsetup_token_dump(
         crypt_log(cd, "\ttpm2-policy-hash:" CRYPT_DUMP_LINE_SEP "%s\n", policy_hash_str);
         crypt_log(cd, "\ttpm2-pin:         %s\n", true_false(flags & TPM2_FLAGS_USE_PIN));
         crypt_log(cd, "\ttpm2-pcrlock:     %s\n", true_false(flags & TPM2_FLAGS_USE_PCRLOCK));
-        crypt_log(cd, "\ttpm2-salt:        %s\n", true_false(salt));
-        crypt_log(cd, "\ttpm2-srk:         %s\n", true_false(srk_buf));
+        crypt_log(cd, "\ttpm2-salt:        %s\n", true_false(iovec_is_set(&salt)));
+        crypt_log(cd, "\ttpm2-srk:         %s\n", true_false(iovec_is_set(&srk)));
 }
 
 /*
index 72be5cc71d3b4453d26d936778479977f294ef7b..e2e4d0dc049b7aec121b6cc737b35748c92059ac 100644 (file)
@@ -17,33 +17,26 @@ int acquire_luks2_key(
                 const char *device,
                 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,
                 const char *signature_path,
                 const char *pin,
                 const char *pcrlock_path,
                 uint16_t primary_alg,
-                const void *key_data,
-                size_t key_data_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,
-                void **ret_decrypted_key,
-                size_t *ret_decrypted_key_size) {
+                struct iovec *ret_decrypted_key) {
 
         _cleanup_(json_variant_unrefp) JsonVariant *signature_json = NULL;
         _cleanup_free_ char *auto_device = NULL;
         _cleanup_(erase_and_freep) char *b64_salted_pin = NULL;
         int r;
 
-        assert(salt || salt_size == 0);
+        assert(iovec_is_valid(salt));
         assert(ret_decrypted_key);
-        assert(ret_decrypted_key_size);
 
         if (!device) {
                 r = tpm2_find_device_auto(&auto_device);
@@ -58,10 +51,10 @@ int acquire_luks2_key(
         if ((flags & TPM2_FLAGS_USE_PIN) && !pin)
                 return -ENOANO;
 
-        if (pin && salt_size > 0) {
+        if (pin && iovec_is_set(salt)) {
                 uint8_t salted_pin[SHA256_DIGEST_SIZE] = {};
                 CLEANUP_ERASE(salted_pin);
-                r = tpm2_util_pbkdf2_hmac_sha256(pin, strlen(pin), salt, salt_size, salted_pin);
+                r = tpm2_util_pbkdf2_hmac_sha256(pin, strlen(pin), salt->iov_base, salt->iov_len, salted_pin);
                 if (r < 0)
                         return log_error_errno(r, "Failed to perform PBKDF2: %m");
 
@@ -92,16 +85,16 @@ int acquire_luks2_key(
         r = tpm2_unseal(tpm2_context,
                         hash_pcr_mask,
                         pcr_bank,
-                        pubkey, pubkey_size,
+                        pubkey,
                         pubkey_pcr_mask,
                         signature_json,
                         pin,
                         FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK) ? &pcrlock_policy : NULL,
                         primary_alg,
-                        key_data, key_data_size,
-                        policy_hash, policy_hash_size,
-                        srk_buf, srk_buf_size,
-                        ret_decrypted_key, ret_decrypted_key_size);
+                        blob,
+                        policy_hash,
+                        srk,
+                        ret_decrypted_key);
         if (r < 0)
                 return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
index d84e5a3c3ba713be515c6a546aa8ea5d721fc2ed..20151d6ca9f89b037491b1dfc40d6b8165567c5c 100644 (file)
@@ -10,21 +10,15 @@ int acquire_luks2_key(
                 const char *device,
                 uint32_t pcr_mask,
                 uint16_t pcr_bank,
-                const void *pubkey,
-                size_t pubkey_size,
+                const struct iovec *pubkey,
                 uint32_t pubkey_pcr_mask,
                 const char *signature_path,
                 const char *pcrlock_path,
                 const char *pin,
                 uint16_t primary_alg,
-                const void *key_data,
-                size_t key_data_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 *key_data,
+                const struct iovec *policy_hash,
+                const struct iovec *salt,
+                const struct iovec *srk,
                 TPM2Flags flags,
-                void **ret_decrypted_key,
-                size_t *ret_decrypted_key_size);
+                struct iovec *decrypted_key);
index f59d5f9d1dc0b8cdc041606324c63183657f1c23..fc0ec443a512a9e486d867131b3c358971b9742c 100644 (file)
@@ -58,8 +58,7 @@ int acquire_tpm2_key(
                 const char *device,
                 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,
                 const char *signature_path,
                 const char *pcrlock_path,
@@ -67,29 +66,23 @@ int acquire_tpm2_key(
                 const char *key_file,
                 size_t key_file_size,
                 uint64_t key_file_offset,
-                const void *key_data,
-                size_t key_data_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 *key_data,
+                const struct iovec *policy_hash,
+                const struct iovec *salt,
+                const struct iovec *srk,
                 TPM2Flags flags,
                 usec_t until,
                 bool headless,
                 AskPasswordFlags ask_password_flags,
-                void **ret_decrypted_key,
-                size_t *ret_decrypted_key_size) {
+                struct iovec *ret_decrypted_key) {
 
         _cleanup_(json_variant_unrefp) JsonVariant *signature_json = NULL;
         _cleanup_free_ void *loaded_blob = NULL;
         _cleanup_free_ char *auto_device = NULL;
-        size_t blob_size;
-        const void *blob;
+        struct iovec blob;
         int r;
 
-        assert(salt || salt_size == 0);
+        assert(iovec_is_valid(salt));
 
         if (!device) {
                 r = tpm2_find_device_auto(&auto_device);
@@ -101,10 +94,9 @@ int acquire_tpm2_key(
                 device = auto_device;
         }
 
-        if (key_data) {
-                blob = key_data;
-                blob_size = key_data_size;
-        } else {
+        if (iovec_is_set(key_data))
+                blob = *key_data;
+        else {
                 _cleanup_free_ char *bindname = NULL;
 
                 /* If we read the salt via AF_UNIX, make this client recognizable */
@@ -117,11 +109,11 @@ int acquire_tpm2_key(
                                 key_file_size == 0 ? SIZE_MAX : key_file_size,
                                 READ_FULL_FILE_CONNECT_SOCKET,
                                 bindname,
-                                (char**) &loaded_blob, &blob_size);
+                                (char**) &loaded_blob, &blob.iov_len);
                 if (r < 0)
                         return r;
 
-                blob = loaded_blob;
+                blob.iov_base = loaded_blob;
         }
 
         if (pubkey_pcr_mask != 0) {
@@ -147,20 +139,16 @@ int acquire_tpm2_key(
                 r = tpm2_unseal(tpm2_context,
                                 hash_pcr_mask,
                                 pcr_bank,
-                                pubkey, pubkey_size,
+                                pubkey,
                                 pubkey_pcr_mask,
                                 signature_json,
                                 /* pin= */ NULL,
                                 FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK) ? &pcrlock_policy : NULL,
                                 primary_alg,
-                                blob,
-                                blob_size,
+                                &blob,
                                 policy_hash,
-                                policy_hash_size,
-                                srk_buf,
-                                srk_buf_size,
-                                ret_decrypted_key,
-                                ret_decrypted_key_size);
+                                srk,
+                                ret_decrypted_key);
                 if (r < 0)
                         return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
@@ -177,11 +165,11 @@ int acquire_tpm2_key(
                 if (r < 0)
                         return r;
 
-                if (salt_size > 0) {
+                if (iovec_is_set(salt)) {
                         uint8_t salted_pin[SHA256_DIGEST_SIZE] = {};
                         CLEANUP_ERASE(salted_pin);
 
-                        r = tpm2_util_pbkdf2_hmac_sha256(pin_str, strlen(pin_str), salt, salt_size, salted_pin);
+                        r = tpm2_util_pbkdf2_hmac_sha256(pin_str, strlen(pin_str), salt->iov_base, salt->iov_len, salted_pin);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to perform PBKDF2: %m");
 
@@ -195,20 +183,16 @@ int acquire_tpm2_key(
                 r = tpm2_unseal(tpm2_context,
                                 hash_pcr_mask,
                                 pcr_bank,
-                                pubkey, pubkey_size,
+                                pubkey,
                                 pubkey_pcr_mask,
                                 signature_json,
                                 b64_salted_pin,
                                 pcrlock_path ? &pcrlock_policy : NULL,
                                 primary_alg,
-                                blob,
-                                blob_size,
+                                &blob,
                                 policy_hash,
-                                policy_hash_size,
-                                srk_buf,
-                                srk_buf_size,
-                                ret_decrypted_key,
-                                ret_decrypted_key_size);
+                                srk,
+                                ret_decrypted_key);
                 if (r < 0) {
                         log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
@@ -228,18 +212,13 @@ int find_tpm2_auto_data(
                 int start_token,
                 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,
                 int *ret_keyslot,
                 int *ret_token) {
@@ -249,9 +228,8 @@ int find_tpm2_auto_data(
         assert(cd);
 
         for (token = start_token; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
-                _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
+                _cleanup_(iovec_done) struct iovec blob = {}, policy_hash = {}, pubkey = {}, salt = {}, srk = {};
                 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-                size_t blob_size, policy_hash_size, pubkey_size, salt_size = 0, srk_buf_size = 0;
                 uint32_t hash_pcr_mask, pubkey_pcr_mask;
                 uint16_t pcr_bank, primary_alg;
                 TPM2Flags flags;
@@ -268,13 +246,13 @@ int find_tpm2_auto_data(
                                 &keyslot,
                                 &hash_pcr_mask,
                                 &pcr_bank,
-                                &pubkey, &pubkey_size,
+                                &pubkey,
                                 &pubkey_pcr_mask,
                                 &primary_alg,
-                                &blob, &blob_size,
-                                &policy_hash, &policy_hash_size,
-                                &salt, &salt_size,
-                                &srk_buf, &srk_buf_size,
+                                &blob,
+                                &policy_hash,
+                                &salt,
+                                &srk,
                                 &flags);
                 if (r == -EUCLEAN) /* Gracefully handle issues in JSON fields not owned by us */
                         continue;
@@ -289,20 +267,15 @@ int find_tpm2_auto_data(
 
                         *ret_hash_pcr_mask = hash_pcr_mask;
                         *ret_pcr_bank = pcr_bank;
-                        *ret_pubkey = TAKE_PTR(pubkey);
-                        *ret_pubkey_size = pubkey_size;
+                        *ret_pubkey = TAKE_STRUCT(pubkey);
                         *ret_pubkey_pcr_mask = pubkey_pcr_mask;
                         *ret_primary_alg = primary_alg;
-                        *ret_blob = TAKE_PTR(blob);
-                        *ret_blob_size = blob_size;
-                        *ret_policy_hash = TAKE_PTR(policy_hash);
-                        *ret_policy_hash_size = policy_hash_size;
-                        *ret_salt = TAKE_PTR(salt);
-                        *ret_salt_size = salt_size;
+                        *ret_blob = TAKE_STRUCT(blob);
+                        *ret_policy_hash = TAKE_STRUCT(policy_hash);
+                        *ret_salt = TAKE_STRUCT(salt);
                         *ret_keyslot = keyslot;
                         *ret_token = token;
-                        *ret_srk_buf = TAKE_PTR(srk_buf);
-                        *ret_srk_buf_size = srk_buf_size;
+                        *ret_srk = TAKE_STRUCT(srk);
                         *ret_flags = flags;
                         return 0;
                 }
index a50a9435a986759323e5dd75f90e66ba21c5e478..a593e043749ab1d83cab678d028cfdd827220576 100644 (file)
@@ -16,8 +16,7 @@ int acquire_tpm2_key(
                 const char *device,
                 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,
                 const char *signature_path,
                 const char *pcrlock_path,
@@ -25,20 +24,15 @@ int acquire_tpm2_key(
                 const char *key_file,
                 size_t key_file_size,
                 uint64_t key_file_offset,
-                const void *key_data,
-                size_t key_data_size,
-                const void *policy_hash,
-                size_t policy_hash_size,
-                const void *salt,
-                size_t salt_size,
-                const void *srk_buf,
-                size_t salt_srk_buf_size,
+                const struct iovec *key_data,
+                const struct iovec *policy_hash,
+                const struct iovec *salt,
+                const struct iovec *srk,
                 TPM2Flags flags,
                 usec_t until,
                 bool headless,
                 AskPasswordFlags ask_password_flags,
-                void **ret_decrypted_key,
-                size_t *ret_decrypted_key_size);
+                struct iovec *ret_decrypted_key);
 
 int find_tpm2_auto_data(
                 struct crypt_device *cd,
@@ -46,18 +40,13 @@ int find_tpm2_auto_data(
                 int start_token,
                 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_size,
+                struct iovec *ret_blob,
+                struct iovec *ret_policy_hash,
+                struct iovec *ret_salt,
+                struct iovec *ret_srk,
                 TPM2Flags *ret_flags,
                 int *ret_keyslot,
                 int *ret_token);
@@ -69,8 +58,7 @@ static inline int acquire_tpm2_key(
                 const char *device,
                 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,
                 const char *signature_path,
                 const char *pcrlock_path,
@@ -78,20 +66,15 @@ static inline int acquire_tpm2_key(
                 const char *key_file,
                 size_t key_file_size,
                 uint64_t key_file_offset,
-                const void *key_data,
-                size_t key_data_size,
-                const void *policy_hash,
-                size_t policy_hash_size,
-                const void *salt,
-                size_t salt_size,
-                const void *srk_buf,
-                size_t salt_srk_buf_size,
+                const struct iovec *key_data,
+                const struct iovec *policy_hash,
+                const struct iovec *salt,
+                const struct iovec *srk,
                 TPM2Flags flags,
                 usec_t until,
                 bool headless,
                 AskPasswordFlags ask_password_flags,
-                void **ret_decrypted_key,
-                size_t *ret_decrypted_key_size) {
+                struct iovec *ret_decrypted_key) {
 
         return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
                                "TPM2 support not available.");
@@ -103,18 +86,13 @@ static inline int find_tpm2_auto_data(
                 int start_token,
                 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_size,
+                struct iovec *ret_blob,
+                struct iovec *ret_policy_hash,
+                struct iovec *ret_salt,
+                struct iovec *ret_srk,
                 TPM2Flags *ret_flags,
                 int *ret_keyslot,
                 int *ret_token) {
index b56b51a134f2eb761fa4fdcff81c472fcdec7e5b..80f8f91948fb52fc14f2c372ebe19029119e607e 100644 (file)
@@ -1650,18 +1650,16 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                 struct crypt_device *cd,
                 const char *name,
                 const char *key_file,
-                const void *key_data,
-                size_t key_data_size,
+                const struct iovec *key_data,
                 usec_t until,
                 uint32_t flags,
                 bool pass_volume_key) {
 
         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
-        _cleanup_(erase_and_freep) void *decrypted_key = NULL;
+        _cleanup_(iovec_done_erase) struct iovec decrypted_key = {};
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_free_ char *friendly = NULL;
         int keyslot = arg_key_slot, r;
-        size_t decrypted_key_size;
 
         assert(cd);
         assert(name);
@@ -1672,7 +1670,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                 return log_oom();
 
         for (;;) {
-                if (key_file || key_data) {
+                if (key_file || iovec_is_set(key_data)) {
                         /* If key data is specified, use that */
 
                         r = acquire_tpm2_key(
@@ -1680,21 +1678,21 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                         arg_tpm2_device,
                                         arg_tpm2_pcr_mask == UINT32_MAX ? TPM2_PCR_MASK_DEFAULT : arg_tpm2_pcr_mask,
                                         UINT16_MAX,
-                                        /* pubkey= */ NULL, /* pubkey_size= */ 0,
+                                        /* pubkey= */ NULL,
                                         /* pubkey_pcr_mask= */ 0,
                                         /* signature_path= */ NULL,
                                         /* pcrlock_path= */ NULL,
                                         /* primary_alg= */ 0,
                                         key_file, arg_keyfile_size, arg_keyfile_offset,
-                                        key_data, key_data_size,
-                                        /* policy_hash= */ NULL, /* policy_hash_size= */ 0, /* we don't know the policy hash */
-                                        /* salt= */ NULL, /* salt_size= */ 0,
-                                        /* srk_buf= */ NULL, /* srk_buf_size= */ 0,
+                                        key_data,
+                                        /* policy_hash= */ NULL, /* we don't know the policy hash */
+                                        /* salt= */ NULL,
+                                        /* srk= */ NULL,
                                         arg_tpm2_pin ? TPM2_FLAGS_USE_PIN : 0,
                                         until,
                                         arg_headless,
                                         arg_ask_password_flags,
-                                        &decrypted_key, &decrypted_key_size);
+                                        &decrypted_key);
                         if (r >= 0)
                                 break;
                         if (IN_SET(r, -EACCES, -ENOLCK))
@@ -1725,8 +1723,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                 }
 
                 if (r == -EOPNOTSUPP) { /* Plugin not available, let's process TPM2 stuff right here instead */
-                        _cleanup_free_ void *blob = NULL, *policy_hash = NULL;
-                        size_t blob_size, policy_hash_size;
+                        _cleanup_(iovec_done) struct iovec blob = {}, policy_hash = {};
                         bool found_some = false;
                         int token = 0; /* first token to look at */
 
@@ -1735,8 +1732,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                          * works. */
 
                         for (;;) {
-                                _cleanup_free_ void *pubkey = NULL, *salt = NULL, *srk_buf = NULL;
-                                size_t pubkey_size = 0, salt_size = 0, srk_buf_size = 0;
+                                _cleanup_(iovec_done) struct iovec pubkey = {}, salt = {}, srk = {};
                                 uint32_t hash_pcr_mask, pubkey_pcr_mask;
                                 uint16_t pcr_bank, primary_alg;
                                 TPM2Flags tpm2_flags;
@@ -1747,13 +1743,13 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                                 token, /* search for the token with this index, or any later index than this */
                                                 &hash_pcr_mask,
                                                 &pcr_bank,
-                                                &pubkey, &pubkey_size,
+                                                &pubkey,
                                                 &pubkey_pcr_mask,
                                                 &primary_alg,
-                                                &blob, &blob_size,
-                                                &policy_hash, &policy_hash_size,
-                                                &salt, &salt_size,
-                                                &srk_buf, &srk_buf_size,
+                                                &blob,
+                                                &policy_hash,
+                                                &salt,
+                                                &srk,
                                                 &tpm2_flags,
                                                 &keyslot,
                                                 &token);
@@ -1778,21 +1774,21 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                                 arg_tpm2_device,
                                                 hash_pcr_mask,
                                                 pcr_bank,
-                                                pubkey, pubkey_size,
+                                                &pubkey,
                                                 pubkey_pcr_mask,
                                                 arg_tpm2_signature,
                                                 arg_tpm2_pcrlock,
                                                 primary_alg,
                                                 /* key_file= */ NULL, /* key_file_size= */ 0, /* key_file_offset= */ 0, /* no key file */
-                                                blob, blob_size,
-                                                policy_hash, policy_hash_size,
-                                                salt, salt_size,
-                                                srk_buf, srk_buf_size,
+                                                &blob,
+                                                &policy_hash,
+                                                &salt,
+                                                &srk,
                                                 tpm2_flags,
                                                 until,
                                                 arg_headless,
                                                 arg_ask_password_flags,
-                                                &decrypted_key, &decrypted_key_size);
+                                                &decrypted_key);
                                 if (IN_SET(r, -EACCES, -ENOLCK))
                                         return log_notice_errno(SYNTHETIC_ERRNO(EAGAIN), "TPM2 PIN unlock failed, falling back to traditional unlocking.");
                                 if (r != -EPERM)
@@ -1837,17 +1833,16 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
 
                 log_debug("Got one or more potentially relevant udev events, rescanning for TPM2...");
         }
-        assert(decrypted_key);
 
         if (pass_volume_key)
-                r = measured_crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, flags);
+                r = measured_crypt_activate_by_volume_key(cd, name, decrypted_key.iov_base, decrypted_key.iov_len, flags);
         else {
                 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
                 ssize_t base64_encoded_size;
 
                 /* Before using this key as passphrase we base64 encode it, for compat with homed */
 
-                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+                base64_encoded_size = base64mem(decrypted_key.iov_base, decrypted_key.iov_len, &base64_encoded);
                 if (base64_encoded_size < 0)
                         return log_oom();
 
@@ -2045,7 +2040,7 @@ static int attach_luks_or_plain_or_bitlk(
                  crypt_get_device_name(cd));
 
         if (arg_tpm2_device || arg_tpm2_device_auto)
-                return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, key_data_size, until, flags, pass_volume_key);
+                return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, &IOVEC_MAKE(key_data, key_data_size), until, flags, pass_volume_key);
         if (arg_fido2_device || arg_fido2_device_auto)
                 return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data, key_data_size, until, flags, pass_volume_key);
         if (arg_pkcs11_uri || arg_pkcs11_uri_auto)
index 95cae94a8e069af60d0a5bfaf0a0833e8cff4abe..b241f9bc61a137e1b7fcf940437cc0ebfbb03583 100644 (file)
@@ -3774,17 +3774,15 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
 
         if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
 #if HAVE_TPM2
+                _cleanup_(iovec_done) struct iovec pubkey = {}, blob = {}, srk = {};
+                _cleanup_(iovec_done_erase) struct iovec secret = {};
                 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-                _cleanup_(erase_and_freep) void *secret = NULL;
-                _cleanup_free_ void *pubkey = NULL;
-                _cleanup_free_ void *blob = NULL, *srk_buf = NULL;
-                size_t secret_size, blob_size, pubkey_size = 0, srk_buf_size = 0;
                 ssize_t base64_encoded_size;
                 int keyslot;
                 TPM2Flags flags = 0;
 
                 if (arg_tpm2_public_key_pcr_mask != 0) {
-                        r = tpm2_load_pcr_public_key(arg_tpm2_public_key, &pubkey, &pubkey_size);
+                        r = tpm2_load_pcr_public_key(arg_tpm2_public_key, &pubkey.iov_base, &pubkey.iov_len);
                         if (r < 0) {
                                 if (arg_tpm2_public_key || r != -ENOENT)
                                         return log_error_errno(r, "Failed to read TPM PCR public key: %m");
@@ -3795,8 +3793,8 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
                 }
 
                 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");
                 }
@@ -3853,7 +3851,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
                 r = tpm2_calculate_sealing_policy(
                                 arg_tpm2_hash_pcr_values,
                                 arg_tpm2_n_hash_pcr_values,
-                                pubkey ? &public : NULL,
+                                iovec_is_set(&pubkey) ? &public : NULL,
                                 /* use_pin= */ false,
                                 arg_tpm2_pcrlock ? &pcrlock_policy : NULL,
                                 &policy);
@@ -3865,25 +3863,25 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
                                         arg_tpm2_seal_key_handle,
                                         &device_key_public,
                                         /* attributes= */ NULL,
-                                        /* secret= */ NULL, /* secret_size= */ 0,
+                                        /* secret= */ NULL,
                                         &policy,
                                         /* pin= */ NULL,
-                                        &secret, &secret_size,
-                                        &blob, &blob_size,
-                                        &srk_buf, &srk_buf_size);
+                                        &secret,
+                                        &blob,
+                                        &srk);
                 else
                         r = tpm2_seal(tpm2_context,
                                       arg_tpm2_seal_key_handle,
                                       &policy,
                                       /* pin= */ NULL,
-                                      &secret, &secret_size,
-                                      &blob, &blob_size,
+                                      &secret,
+                                      &blob,
                                       /* ret_primary_alg= */ NULL,
-                                      &srk_buf, &srk_buf_size);
+                                      &srk);
                 if (r < 0)
                         return log_error_errno(r, "Failed to seal to TPM2: %m");
 
-                base64_encoded_size = base64mem(secret, secret_size, &base64_encoded);
+                base64_encoded_size = base64mem(secret.iov_base, secret.iov_len, &base64_encoded);
                 if (base64_encoded_size < 0)
                         return log_error_errno(base64_encoded_size, "Failed to base64 encode secret key: %m");
 
@@ -3905,13 +3903,13 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
                                 keyslot,
                                 hash_pcr_mask,
                                 hash_pcr_bank,
-                                pubkey, pubkey_size,
+                                &pubkey,
                                 arg_tpm2_public_key_pcr_mask,
                                 /* primary_alg= */ 0,
-                                blob, blob_size,
-                                policy.buffer, policy.size,
-                                NULL, 0, /* no salt because tpm2_seal has no pin */
-                                srk_buf, srk_buf_size,
+                                &blob,
+                                &IOVEC_MAKE(policy.buffer, policy.size),
+                                /* salt= */ NULL, /* no salt because tpm2_seal has no pin */
+                                &srk,
                                 flags,
                                 &v);
                 if (r < 0)
index 22c5e4231104b449506925c97daa1d6290840988..716543a2a78933811bf6185a8e5288612c634716 100644 (file)
@@ -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.");
 }
 
index b34dba7cc2fc5c2fadd18fbef86060c7cf62ba04..38d5086e8cf5b2ba8c5c10935e7ff3d0fc719ed2 100644 (file)
@@ -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);
index 2c49dece020fd24d465aa3968a061804eecfa5b5..bec84a3f03c3383036d4be08d7161f21d34393bb 100644 (file)
@@ -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;
 }
index 55d748159f3f314e300e420d5ed271cdbe9cd7df..e94b345de7647223649295f85da757a76b163740 100644 (file)
@@ -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)
index 19881c6e91f447bbd8dbef3de8316bb389a49836..eeaf0b7b8854a36aea553c9aa91d566057473cbc 100644 (file)
@@ -1100,42 +1100,38 @@ static void calculate_seal_and_unseal(
         assert_se(asprintf(&secret_string, "The classified documents are in room %x", parent_index) > 0);
         size_t secret_size = strlen(secret_string) + 1;
 
-        _cleanup_free_ void *blob = NULL;
-        size_t blob_size = 0;
-        _cleanup_free_ void *serialized_parent = NULL;
-        size_t serialized_parent_size;
+        _cleanup_(iovec_done) struct iovec blob = {}, serialized_parent = {};
         assert_se(tpm2_calculate_seal(
                         parent_index,
                         parent_public,
                         /* attributes= */ NULL,
-                        secret_string, secret_size,
+                        &IOVEC_MAKE(secret_string, secret_size),
                         /* policy= */ NULL,
                         /* pin= */ NULL,
-                        /* ret_secret= */ NULL, /* ret_secret_size= */ 0,
-                        &blob, &blob_size,
-                        &serialized_parent, &serialized_parent_size) >= 0);
+                        /* ret_secret= */ NULL,
+                        &blob,
+                        &serialized_parent) >= 0);
 
-        _cleanup_free_ void *unsealed_secret = NULL;
-        size_t unsealed_secret_size;
+        _cleanup_(iovec_done) struct iovec unsealed_secret = {};
         assert_se(tpm2_unseal(
                         c,
                         /* hash_pcr_mask= */ 0,
                         /* pcr_bank= */ 0,
-                        /* pubkey= */ NULL, /* pubkey_size= */ 0,
+                        /* pubkey= */ NULL,
                         /* pubkey_pcr_mask= */ 0,
                         /* signature= */ NULL,
                         /* pin= */ NULL,
                         /* pcrlock_policy= */ NULL,
                         /* primary_alg= */ 0,
-                        blob, blob_size,
-                        /* known_policy_hash= */ NULL, /* known_policy_hash_size= */ 0,
-                        serialized_parent, serialized_parent_size,
-                        &unsealed_secret, &unsealed_secret_size) >= 0);
+                        &blob,
+                        /* known_policy_hash= */ NULL,
+                        &serialized_parent,
+                        &unsealed_secret) >= 0);
 
-        assert_se(memcmp_nn(secret_string, secret_size, unsealed_secret, unsealed_secret_size) == 0);
+        assert_se(memcmp_nn(secret_string, secret_size, unsealed_secret.iov_base, unsealed_secret.iov_len) == 0);
 
-        char unsealed_string[unsealed_secret_size];
-        assert_se(snprintf(unsealed_string, unsealed_secret_size, "%s", (char*) unsealed_secret) == (int) unsealed_secret_size - 1);
+        char unsealed_string[unsealed_secret.iov_len];
+        assert_se(snprintf(unsealed_string, unsealed_secret.iov_len, "%s", (char*) unsealed_secret.iov_base) == (int) unsealed_secret.iov_len - 1);
         log_debug("Unsealed secret is: %s", unsealed_string);
 }
 
@@ -1187,34 +1183,33 @@ static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) {
 
         log_debug("Check seal/unseal for handle 0x%" PRIx32, handle);
 
-        _cleanup_free_ void *secret = NULL, *blob = NULL, *srk = NULL, *unsealed_secret = NULL;
-        size_t secret_size, blob_size, srk_size, unsealed_secret_size;
+        _cleanup_(iovec_done) struct iovec secret = {}, blob = {}, srk = {}, unsealed_secret = {};
         assert_se(tpm2_seal(
                         c,
                         handle,
                         &policy,
                         /* pin= */ NULL,
-                        &secret, &secret_size,
-                        &blob, &blob_size,
+                        &secret,
+                        &blob,
                         /* ret_primary_alg= */ NULL,
-                        &srk, &srk_size) >= 0);
+                        &srk) >= 0);
 
         assert_se(tpm2_unseal(
                         c,
                         /* hash_pcr_mask= */ 0,
                         /* pcr_bank= */ 0,
-                        /* pubkey= */ NULL, /* pubkey_size= */ 0,
+                        /* pubkey= */ NULL,
                         /* pubkey_pcr_mask= */ 0,
                         /* signature= */ NULL,
                         /* pin= */ NULL,
                         /* pcrlock_policy= */ NULL,
                         /* primary_alg= */ 0,
-                        blob, blob_size,
-                        /* policy_hash= */ NULL, /* policy_hash_size= */ 0,
-                        srk, srk_size,
-                        &unsealed_secret, &unsealed_secret_size) >= 0);
+                        &blob,
+                        /* policy_hash= */ NULL,
+                        &srk,
+                        &unsealed_secret) >= 0);
 
-        assert_se(memcmp_nn(secret, secret_size, unsealed_secret, unsealed_secret_size) == 0);
+        assert_se(iovec_memcmp(&secret, &unsealed_secret) == 0);
 }
 
 static void check_seal_unseal(Tpm2Context *c) {