]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/cryptsetup/cryptsetup.c
tree-wide: fix return value handling of base64mem()
[thirdparty/systemd.git] / src / cryptsetup / cryptsetup.c
index f0130eb238889bd027f9e921f140e7191a7d5d7a..cd2065f480bb3cea7cb616cf6e30540e97729595 100644 (file)
@@ -43,8 +43,8 @@
 /* internal helper */
 #define ANY_LUKS "LUKS"
 /* as in src/cryptsetup.h */
-#define CRYPT_SECTOR_SIZE 512
-#define CRYPT_MAX_SECTOR_SIZE 4096
+#define CRYPT_SECTOR_SIZE 512U
+#define CRYPT_MAX_SECTOR_SIZE 4096U
 
 typedef enum PassphraseType {
         PASSPHRASE_NONE,
@@ -92,6 +92,7 @@ static char *arg_fido2_rp_id = NULL;
 static char *arg_tpm2_device = NULL;
 static bool arg_tpm2_device_auto = false;
 static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
+static char *arg_tpm2_signature = NULL;
 static bool arg_tpm2_pin = false;
 static bool arg_headless = false;
 static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
@@ -105,6 +106,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_fido2_cid, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
 
 static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
         [PASSPHRASE_REGULAR] = "passphrase",
@@ -394,20 +396,19 @@ static int parse_one_option(const char *option) {
 
         } else if ((val = startswith(option, "tpm2-pcrs="))) {
 
-                if (isempty(val))
-                        arg_tpm2_pcr_mask = 0;
-                else {
-                        uint32_t mask;
+                r = tpm2_parse_pcr_argument(val, &arg_tpm2_pcr_mask);
+                if (r < 0)
+                        return r;
 
-                        r = tpm2_parse_pcrs(val, &mask);
-                        if (r < 0)
-                                return r;
+        } else if ((val = startswith(option, "tpm2-signature="))) {
 
-                        if (arg_tpm2_pcr_mask == UINT32_MAX)
-                                arg_tpm2_pcr_mask = mask;
-                        else
-                                arg_tpm2_pcr_mask |= mask;
-                }
+                if (!path_is_absolute(val))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "TPM2 signature path \"%s\" is not absolute, refusing.", val);
+
+                r = free_and_strdup(&arg_tpm2_signature, val);
+                if (r < 0)
+                        return log_oom();
 
         } else if ((val = startswith(option, "tpm2-pin="))) {
 
@@ -493,7 +494,7 @@ static char* disk_description(const char *path) {
                 "ID_MODEL\0";
 
         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
-        const char *i, *name;
+        const char *name;
         struct stat st;
 
         assert(path);
@@ -869,6 +870,8 @@ static int make_security_device_monitor(
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate device monitor: %m");
 
+        (void) sd_device_monitor_set_description(monitor, "security-device");
+
         r = sd_device_monitor_filter_add_match_tag(monitor, "security-device");
         if (r < 0)
                 return log_error_errno(r, "Failed to configure device monitor: %m");
@@ -1058,9 +1061,8 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
         _cleanup_(erase_and_freep) void *decrypted_key = NULL;
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
-        _cleanup_free_ void *discovered_salt = NULL, *discovered_cid = NULL;
-        size_t discovered_salt_size, discovered_cid_size, decrypted_key_size, cid_size = 0;
-        _cleanup_free_ char *friendly = NULL, *discovered_rp_id = NULL;
+        size_t decrypted_key_size, cid_size = 0;
+        _cleanup_free_ char *friendly = NULL;
         int keyslot = arg_key_slot, r;
         const char *rp_id = NULL;
         const void *cid = NULL;
@@ -1085,32 +1087,6 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
                  * use PIN + UP when needed, and do not configure UV at all. Eventually, we should make this
                  * explicitly configurable. */
                 required = FIDO2ENROLL_PIN_IF_NEEDED | FIDO2ENROLL_UP_IF_NEEDED | FIDO2ENROLL_UV_OMIT;
-        } else if (!use_libcryptsetup_plugin) {
-                r = find_fido2_auto_data(
-                                cd,
-                                &discovered_rp_id,
-                                &discovered_salt,
-                                &discovered_salt_size,
-                                &discovered_cid,
-                                &discovered_cid_size,
-                                &keyslot,
-                                &required);
-
-                if (IN_SET(r, -ENOTUNIQ, -ENXIO))
-                        return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
-                                               "Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
-                if (r < 0)
-                        return r;
-
-                if ((required & (FIDO2ENROLL_PIN | FIDO2ENROLL_UP | FIDO2ENROLL_UV)) && arg_headless)
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOPKG),
-                                               "Local verification is required to unlock this volume, but the 'headless' parameter was set.");
-
-                rp_id = discovered_rp_id;
-                key_data = discovered_salt;
-                key_data_size = discovered_salt_size;
-                cid = discovered_cid;
-                cid_size = discovered_cid_size;
         }
 
         friendly = friendly_disk_name(crypt_get_device_name(cd), name);
@@ -1125,19 +1101,30 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
                                                        "Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
 
                 } else {
-                        r = acquire_fido2_key(
-                                        name,
-                                        friendly,
-                                        arg_fido2_device,
-                                        rp_id,
-                                        cid, cid_size,
-                                        key_file, arg_keyfile_size, arg_keyfile_offset,
-                                        key_data, key_data_size,
-                                        until,
-                                        arg_headless,
-                                        required,
-                                        &decrypted_key, &decrypted_key_size,
-                                        arg_ask_password_flags);
+                        if (cid)
+                                r = acquire_fido2_key(
+                                                name,
+                                                friendly,
+                                                arg_fido2_device,
+                                                rp_id,
+                                                cid, cid_size,
+                                                key_file, arg_keyfile_size, arg_keyfile_offset,
+                                                key_data, key_data_size,
+                                                until,
+                                                arg_headless,
+                                                required,
+                                                &decrypted_key, &decrypted_key_size,
+                                                arg_ask_password_flags);
+                        else
+                                r = acquire_fido2_key_auto(
+                                                cd,
+                                                name,
+                                                friendly,
+                                                arg_fido2_device,
+                                                until,
+                                                arg_headless,
+                                                &decrypted_key, &decrypted_key_size,
+                                                arg_ask_password_flags);
                         if (r >= 0)
                                 break;
                 }
@@ -1173,14 +1160,15 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
                 r = crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, 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 */
 
-                r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
-                if (r < 0)
+                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+                if (base64_encoded_size < 0)
                         return log_oom();
 
-                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, strlen(base64_encoded), flags);
+                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, base64_encoded_size, flags);
         }
         if (r == -EPERM) {
                 log_error_errno(r, "Failed to activate with FIDO2 decrypted key. (Key incorrect?)");
@@ -1320,6 +1308,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
                 r = crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, 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. Why? For compatibility
                  * with homed's PKCS#11 hookup: there we want to use the key we acquired through
@@ -1329,11 +1318,11 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
                  * without embedded NUL here too, and that's easiest to generate from a binary blob
                  * via base64 encoding. */
 
-                r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
-                if (r < 0)
+                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+                if (base64_encoded_size < 0)
                         return log_oom();
 
-                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, strlen(base64_encoded), flags);
+                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, base64_encoded_size, flags);
         }
         if (r == -EPERM) {
                 log_error_errno(r, "Failed to activate with PKCS#11 decrypted key. (Key incorrect?)");
@@ -1368,6 +1357,8 @@ static int make_tpm2_device_monitor(
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate device monitor: %m");
 
+        (void) sd_device_monitor_set_description(monitor, "tpmrm");
+
         r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, "tpmrm", NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to configure device monitor: %m");
@@ -1395,7 +1386,8 @@ static int attach_luks2_by_tpm2_via_plugin(
 #if HAVE_LIBCRYPTSETUP_PLUGINS
         systemd_tpm2_plugin_params params = {
                 .search_pcr_mask = arg_tpm2_pcr_mask,
-                .device = arg_tpm2_device
+                .device = arg_tpm2_device,
+                .signature_path = arg_tpm2_signature,
         };
 
         if (!libcryptsetup_plugins_support())
@@ -1452,11 +1444,14 @@ 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,
-                                        0,
+                                        /* pubkey= */ NULL, /* pubkey_size= */ 0,
+                                        /* pubkey_pcr_mask= */ 0,
+                                        /* signature_path= */ NULL,
+                                        /* primary_alg= */ 0,
                                         key_file, arg_keyfile_size, arg_keyfile_offset,
                                         key_data, key_data_size,
-                                        NULL, 0, /* we don't know the policy hash */
-                                        arg_tpm2_pin,
+                                        /* policy_hash= */ NULL, /* policy_hash_size= */ 0, /* we don't know the policy hash */
+                                        arg_tpm2_pin ? TPM2_FLAGS_USE_PIN : 0,
                                         until,
                                         arg_headless,
                                         arg_ask_password_flags,
@@ -1501,7 +1496,9 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                          * works. */
 
                         for (;;) {
-                                uint32_t pcr_mask;
+                                _cleanup_free_ void *pubkey = NULL;
+                                size_t pubkey_size = 0;
+                                uint32_t hash_pcr_mask, pubkey_pcr_mask;
                                 uint16_t pcr_bank, primary_alg;
                                 TPM2Flags tpm2_flags;
 
@@ -1509,14 +1506,16 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                                 cd,
                                                 arg_tpm2_pcr_mask, /* if != UINT32_MAX we'll only look for tokens with this PCR mask */
                                                 token, /* search for the token with this index, or any later index than this */
-                                                &pcr_mask,
+                                                &hash_pcr_mask,
                                                 &pcr_bank,
+                                                &pubkey, &pubkey_size,
+                                                &pubkey_pcr_mask,
                                                 &primary_alg,
                                                 &blob, &blob_size,
                                                 &policy_hash, &policy_hash_size,
+                                                &tpm2_flags,
                                                 &keyslot,
-                                                &token,
-                                                &tpm2_flags);
+                                                &token);
                                 if (r == -ENXIO)
                                         /* No further TPM2 tokens found in the LUKS2 header. */
                                         return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
@@ -1534,10 +1533,13 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                 r = acquire_tpm2_key(
                                                 name,
                                                 arg_tpm2_device,
-                                                pcr_mask,
+                                                hash_pcr_mask,
                                                 pcr_bank,
+                                                pubkey, pubkey_size,
+                                                pubkey_pcr_mask,
+                                                arg_tpm2_signature,
                                                 primary_alg,
-                                                NULL, 0, 0, /* no key file */
+                                                /* key_file= */ NULL, /* key_file_size= */ 0, /* key_file_offset= */ 0, /* no key file */
                                                 blob, blob_size,
                                                 policy_hash, policy_hash_size,
                                                 tpm2_flags,
@@ -1595,14 +1597,15 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                 r = crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, 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 */
 
-                r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
-                if (r < 0)
+                base64_encoded_size = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+                if (base64_encoded_size < 0)
                         return log_oom();
 
-                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, strlen(base64_encoded), flags);
+                r = crypt_activate_by_passphrase(cd, name, keyslot, base64_encoded, base64_encoded_size, flags);
         }
         if (r == -EPERM) {
                 log_error_errno(r, "Failed to activate with TPM2 decrypted key. (Key incorrect?)");
@@ -1976,7 +1979,8 @@ static int run(int argc, char *argv[]) {
                 if (until == USEC_INFINITY)
                         until = 0;
 
-                arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8));
+                if (arg_key_size == 0)
+                        arg_key_size = 256U / 8U;
 
                 if (key_file) {
                         struct stat st;