Unify dm backend for crypt/verity.
authorMilan Broz <gmazyland@gmail.com>
Fri, 8 Jun 2012 08:12:12 +0000 (10:12 +0200)
committerMilan Broz <gmazyland@gmail.com>
Fri, 8 Jun 2012 08:12:12 +0000 (10:12 +0200)
lib/libdevmapper.c
lib/loopaes/loopaes.c
lib/luks1/keyencryption.c
lib/luks1/keymanage.c
lib/setup.c
lib/utils_dm.h
lib/verity/verity.c

index 88c529a..f2e66a4 100644 (file)
@@ -300,15 +300,15 @@ out:
        return params;
 }
 static char *get_dm_verity_params(struct crypt_params_verity *vp,
-                                  struct crypt_dm_active_verity *dmd)
+                                  struct crypt_dm_active_device *dmd)
 {
        int max_size, r;
        char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
 
-       hexroot = crypt_safe_alloc(dmd->root_hash_size * 2 + 1);
+       hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1);
        if (!hexroot)
                goto out;
-       hex_key(hexroot, dmd->root_hash_size, dmd->root_hash);
+       hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash);
 
        hexsalt = crypt_safe_alloc(vp->salt_size * 2 + 1);
        if (!hexsalt)
@@ -316,7 +316,8 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
        hex_key(hexsalt, vp->salt_size, vp->salt);
 
        max_size = strlen(hexroot) + strlen(hexsalt) +
-                  strlen(dmd->data_device) + strlen(dmd->hash_device) +
+                  strlen(dmd->u.verity.data_device) +
+                  strlen(dmd->u.verity.hash_device) +
                   strlen(vp->hash_name) + 128;
 
        params = crypt_safe_alloc(max_size);
@@ -325,9 +326,10 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
 
        r = snprintf(params, max_size,
                     "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s",
-                    vp->version, dmd->data_device, dmd->hash_device,
+                    vp->version, dmd->u.verity.data_device,
+                    dmd->u.verity.hash_device,
                     vp->data_block_size, vp->hash_block_size,
-                    vp->data_size, dmd->hash_offset,
+                    vp->data_size, dmd->u.verity.hash_offset,
                     vp->hash_name, hexroot, hexsalt);
        if (r < 0 || r >= max_size) {
                crypt_safe_free(params);
@@ -579,11 +581,16 @@ out_no_removal:
 int dm_create_device(const char *name,
                     const char *type,
                     struct crypt_dm_active_device *dmd,
+                    void *params,
                     int reload)
 {
        char *table_params = NULL;
 
-       table_params = get_dm_crypt_params(dmd);
+       if (dmd->target == DM_CRYPT)
+               table_params = get_dm_crypt_params(dmd);
+       else if (dmd->target == DM_VERITY)
+               table_params = get_dm_verity_params(params, dmd);
+
        if (!table_params)
                return -EINVAL;
 
@@ -591,20 +598,6 @@ int dm_create_device(const char *name,
                                 dmd->uuid, dmd->size, table_params, reload);
 }
 
-int dm_create_verity(const char *name,
-                    struct crypt_params_verity *params,
-                    struct crypt_dm_active_verity *dmd)
-{
-       char *table_params = NULL;
-
-       table_params = get_dm_verity_params(params, dmd);
-       if (!table_params)
-               return -EINVAL;
-
-       return _dm_create_device(name, CRYPT_VERITY, dmd->data_device, dmd->flags,
-                                NULL, dmd->size, table_params, 0);
-}
-
 static int dm_status_dmi(const char *name, struct dm_info *dmi,
                          const char *target, char **status_line)
 {
@@ -691,48 +684,16 @@ int dm_status_verity_ok(const char *name)
        return r;
 }
 
-int dm_query_device(const char *name, uint32_t get_flags,
-                   struct crypt_dm_active_device *dmd)
+static int _dm_query_crypt(uint32_t get_flags,
+                          struct dm_info *dmi,
+                          char *params,
+                          struct crypt_dm_active_device *dmd)
 {
-       struct dm_task *dmt;
-       struct dm_info dmi;
-       uint64_t start, length, val64;
-       char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
-       const char *tmp_uuid;
-       void *next = NULL;
+       uint64_t val64;
+       char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
        unsigned int i;
-       int r = -EINVAL;
-
-       memset(dmd, 0, sizeof(*dmd));
-
-       if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
-               goto out;
-       if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
-               goto out;
-       if (!dm_task_set_name(dmt, name))
-               goto out;
-       r = -ENODEV;
-       if (!dm_task_run(dmt))
-               goto out;
-
-       r = -EINVAL;
-       if (!dm_task_get_info(dmt, &dmi))
-               goto out;
 
-       if (!dmi.exists) {
-               r = -ENODEV;
-               goto out;
-       }
-
-       tmp_uuid = dm_task_get_uuid(dmt);
-
-       next = dm_get_next_target(dmt, next, &start, &length,
-                                 &target_type, &params);
-       if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
-           start != 0 || next)
-               goto out;
-
-       dmd->size = length;
+       dmd->target = DM_CRYPT;
 
        rcipher = strsep(&params, " ");
        /* cipher */
@@ -742,10 +703,10 @@ int dm_query_device(const char *name, uint32_t get_flags,
        /* skip */
        key_ = strsep(&params, " ");
        if (!params)
-               goto out;
+               return -EINVAL;
        val64 = strtoull(params, &params, 10);
        if (*params != ' ')
-               goto out;
+               return -EINVAL;
        params++;
 
        dmd->u.crypt.iv_offset = val64;
@@ -757,50 +718,47 @@ int dm_query_device(const char *name, uint32_t get_flags,
 
        /*offset */
        if (!params)
-               goto out;
+               return -EINVAL;
        val64 = strtoull(params, &params, 10);
        dmd->u.crypt.offset = val64;
 
        /* Features section, available since crypt target version 1.11 */
        if (*params) {
                if (*params != ' ')
-                       goto out;
+                       return -EINVAL;
                params++;
 
                /* Number of arguments */
                val64 = strtoull(params, &params, 10);
                if (*params != ' ')
-                       goto out;
+                       return -EINVAL;
                params++;
 
                for (i = 0; i < val64; i++) {
                        if (!params)
-                               goto out;
+                               return -EINVAL;
                        arg = strsep(&params, " ");
                        if (!strcasecmp(arg, "allow_discards"))
                                dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
                        else /* unknown option */
-                               goto out;
+                               return -EINVAL;
                }
 
                /* All parameters shold be processed */
                if (params)
-                       goto out;
+                       return -EINVAL;
        }
 
        /* Never allow to return empty key */
-       if ((get_flags & DM_ACTIVE_KEY) && dmi.suspended) {
+       if ((get_flags & DM_ACTIVE_KEY) && dmi->suspended) {
                log_dbg("Cannot read volume key while suspended.");
-               r = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        if (get_flags & DM_ACTIVE_KEYSIZE) {
                dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
-               if (!dmd->u.crypt.vk) {
-                       r = -ENOMEM;
-                       goto out;
-               }
+               if (!dmd->u.crypt.vk)
+                       return -ENOMEM;
 
                if (get_flags & DM_ACTIVE_KEY) {
                        buffer[2] = '\0';
@@ -810,17 +768,79 @@ int dm_query_device(const char *name, uint32_t get_flags,
                                if (endp != &buffer[2]) {
                                        crypt_free_volume_key(dmd->u.crypt.vk);
                                        dmd->u.crypt.vk = NULL;
-                                       r = -EINVAL;
-                                       goto out;
+                                       return -EINVAL;
                                }
                        }
                }
        }
        memset(key_, 0, strlen(key_));
 
+       return 0;
+}
+
+static int _dm_query_verity(uint32_t get_flags,
+                            struct dm_info *dmi,
+                            char *params,
+                            struct crypt_dm_active_device *dmd)
+{
+       dmd->target = DM_VERITY;
+       return -EINVAL;
+}
+
+int dm_query_device(const char *name, uint32_t get_flags,
+                   struct crypt_dm_active_device *dmd)
+{
+       struct dm_task *dmt;
+       struct dm_info dmi;
+       uint64_t start, length;
+       char *target_type, *params;
+       const char *tmp_uuid;
+       void *next = NULL;
+       int r = -EINVAL;
+
+       memset(dmd, 0, sizeof(*dmd));
+
+       if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+               goto out;
+       if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
+               goto out;
+       if (!dm_task_set_name(dmt, name))
+               goto out;
+       r = -ENODEV;
+       if (!dm_task_run(dmt))
+               goto out;
+
+       r = -EINVAL;
+       if (!dm_task_get_info(dmt, &dmi))
+               goto out;
+
+       if (!dmi.exists) {
+               r = -ENODEV;
+               goto out;
+       }
+
+       next = dm_get_next_target(dmt, next, &start, &length,
+                                 &target_type, &params);
+
+       if (!target_type || start != 0 || next)
+               goto out;
+
+       if (!strcmp(target_type, DM_CRYPT_TARGET))
+               r = _dm_query_crypt(get_flags, &dmi, params, dmd);
+       else if (!strcmp(target_type, DM_VERITY_TARGET))
+               r = _dm_query_verity(get_flags, &dmi, params, dmd);
+       else
+               r = -EINVAL;
+
+       if (r < 0)
+               goto out;
+
+       dmd->size = length;
+
        if (dmi.read_only)
                dmd->flags |= CRYPT_ACTIVATE_READONLY;
 
+       tmp_uuid = dm_task_get_uuid(dmt);
        if (!tmp_uuid)
                dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
        else if (get_flags & DM_ACTIVE_UUID) {
@@ -836,14 +856,6 @@ out:
        return r;
 }
 
-int dm_query_verity(const char *name,
-                   struct crypt_dm_active_verity *dmd)
-{
-       int r = -EINVAL;
-
-       return r;
-}
-
 static int _dm_message(const char *name, const char *msg)
 {
        int r = 0;
index 0dd5e11..7a5f67b 100644 (file)
@@ -225,7 +225,7 @@ int LOOPAES_activate(struct crypt_device *cd,
        log_dbg("Trying to activate loop-AES device %s using cipher %s.",
                name, dmd.u.crypt.cipher);
 
-       r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0);
+       r = dm_create_device(name, CRYPT_LOOPAES, &dmd, NULL, 0);
 
        if (!r && !(dm_flags() & req_flags)) {
                log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));
index 3b3cef8..a2e0d31 100644 (file)
@@ -86,7 +86,7 @@ static int setup_mapping(const char *cipher, const char *name,
        dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
        cleaner_size = dmd.size;
 
-       return dm_create_device(name, "TEMP", &dmd, 0);
+       return dm_create_device(name, "TEMP", &dmd, NULL, 0);
 }
 
 static void sigint_handler(int sig __attribute__((unused)))
index e8b277e..95a4d27 100644 (file)
@@ -1062,7 +1062,7 @@ int LUKS1_activate(struct crypt_device *cd,
                return -ENOMEM;
 
        dmd.u.crypt.cipher = dm_cipher;
-       r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0);
+       r = dm_create_device(name, CRYPT_LUKS1, &dmd, NULL, 0);
 
        free(dm_cipher);
        return r;
index 115d558..0d930ef 100644 (file)
@@ -335,7 +335,7 @@ int PLAIN_activate(struct crypt_device *cd,
        log_dbg("Trying to activate PLAIN device %s using cipher %s.",
                name, dmd.u.crypt.cipher);
 
-       r = dm_create_device(name, CRYPT_PLAIN, &dmd, 0);
+       r = dm_create_device(name, CRYPT_PLAIN, &dmd, NULL, 0);
 
        // FIXME
        if (!cd->plain_uuid && dm_query_device(name, DM_ACTIVE_UUID, &dmd) >= 0)
@@ -1195,7 +1195,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
                r = 0;
        } else {
                dmd.size = new_size;
-               r = dm_create_device(name, cd->type, &dmd, 1);
+               r = dm_create_device(name, cd->type, &dmd, NULL, 1);
        }
 out:
        crypt_free_volume_key(dmd.u.crypt.vk);
index 6eb24c1..7a8c8cc 100644 (file)
@@ -73,18 +73,6 @@ struct crypt_dm_active_device {
        } u;
 };
 
-struct crypt_dm_active_verity {
-       const char *data_device;
-       const char *hash_device;
-
-       const char *root_hash;
-       size_t root_hash_size;
-
-       uint64_t hash_offset;   /* hash offset (not header) */
-       uint64_t size;          /* active device size */
-       uint32_t flags;         /* activation flags */
-};
-
 const char *dm_get_dir(void);
 int dm_init(struct crypt_device *context, int check_kernel);
 void dm_exit(void);
@@ -94,15 +82,11 @@ int dm_status_suspended(const char *name);
 int dm_status_verity_ok(const char *name);
 int dm_query_device(const char *name, uint32_t get_flags,
                    struct crypt_dm_active_device *dmd);
-int dm_query_verity(const char *name,
-                   struct crypt_dm_active_verity *dmd);
 int dm_create_device(const char *name,
                      const char *type,
                      struct crypt_dm_active_device *dmd,
+                     void *params,
                      int reload);
-int dm_create_verity(const char *name,
-                    struct crypt_params_verity *params,
-                    struct crypt_dm_active_verity *dmd);
 int dm_suspend_and_wipe_key(const char *name);
 int dm_resume_and_reinstate_key(const char *name,
                                size_t key_size,
index 1bbd8d5..589a28b 100644 (file)
@@ -155,7 +155,7 @@ int VERITY_activate(struct crypt_device *cd,
                     struct crypt_params_verity *verity_hdr,
                     uint32_t flags)
 {
-       struct crypt_dm_active_verity dmd;
+       struct crypt_dm_active_device dmd;
        uint64_t offset = 0;
        int r;
 
@@ -173,20 +173,22 @@ int VERITY_activate(struct crypt_device *cd,
        if (!name)
                return 0;
 
-       dmd.data_device = crypt_get_device_name(cd);
-       dmd.hash_device = hash_device;
-       dmd.root_hash = root_hash;
-       dmd.root_hash_size = root_hash_size;
-       dmd.hash_offset = VERITY_hash_offset_block(verity_hdr),
+       dmd.target = DM_VERITY;
+       dmd.u.verity.data_device = crypt_get_device_name(cd);
+       dmd.u.verity.hash_device = hash_device;
+       dmd.u.verity.root_hash = root_hash;
+       dmd.u.verity.root_hash_size = root_hash_size;
+       dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr),
        dmd.flags = CRYPT_ACTIVATE_READONLY;
        dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512;
+       dmd.uuid = NULL;
 
-       r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
+       r = device_check_and_adjust(cd, dmd.u.verity.data_device, DEV_EXCL,
                                    &dmd.size, &offset, &dmd.flags);
        if (r)
                return r;
 
-       r = dm_create_verity(name, verity_hdr, &dmd);
+       r = dm_create_device(name, CRYPT_VERITY, &dmd, verity_hdr, 0);
        if (!r && !(dm_flags() & DM_VERITY_SUPPORTED)) {
                log_err(cd, _("Kernel doesn't support dm-verity mapping.\n"));
                return -ENOTSUP;