Skip to content
Snippets Groups Projects
encryption_functions.c 4.63 KiB
Newer Older
/**
 * Use cryptsetup to initialise the luks container.
 * It will not be opened (decrypted) yet, but it does check if the container
 * seems usable.
 * @param crypt_device struct to store crypt device context
 * @param crypt_device path to the encrypted container
 * @return             status code
static int container_initialise(struct crypt_device **cd, const char *path)
{
    // Let LUKS initialise the encrypted device.
    int r = crypt_init(cd, path);
    if (r < 0)
    {
        printf("crypt_init() failed for %s.\n", path);
        printf("status: %d.\n", r);
        return r;
    }

    // Load the LUKS header from the block device into the crypt device context.
    r = crypt_load(*cd, CRYPT_LUKS1, NULL);
    if (r < 0)
    {
        printf("crypt_load() failed on device %s.\n",
            crypt_get_device_name(*cd));
    }

    return r;
}

/**
 * Check if the given device is actually an encrypted container.
 * @param path path to the encrypted container
 */
static bool is_encrypted_device (const char *path)
{
    // Let LUKS initialise the encrypted device.
    struct crypt_device *cd;
    int r = container_initialise(&cd, path);
    crypt_free(cd);
    if (r < 0)
    {
        return false;
    }

    return true;
}

/**
 * Use cryptsetup to unlock the luks container.
 * This will create `/dev/mapper/$device_name`.
 * @param path        path to the encrypted container
 * @param device_name name of the mapping
 * @param password    encryption password of the container
 * @return            status code
static int encryption_unlock(const char *path, const char *device_name,
    const char *password)
{
    // Let LUKS initialise the encrypted device.
    struct crypt_device *cd;
    int r = container_initialise(&cd, path);
    if (r < 0)
    {
        printf("crypt_load() failed on device %s.\n",
            crypt_get_device_name(cd));
        crypt_free(cd);
        return r;
    }

    // Create device mapping with name device_name.
    r = crypt_activate_by_passphrase(cd, device_name, CRYPT_ANY_SLOT,
        password, strlen(password), 0);
    if (r < 0)
    {
        printf("Device %s activation failed.\n", device_name);
        crypt_free(cd);
        return r;
    }

    printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
    printf("\tcipher used: %s\n", crypt_get_cipher(cd));
    printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
    printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));

    crypt_free(cd);
    return 0;
}

/**
 * Use cryptsetup to lock the luks container again.
 * @param device_name name of the mapping
 * @return            status code
 */
static int encryption_lock(const char *device_name)
{
    struct crypt_device *cd;
    int r;

    r = crypt_init_by_name(&cd, device_name);
    if (r < 0)
    {
        printf("crypt_init_by_name() failed for %s.\n", device_name);
        return r;
    }

    if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
    {
        printf("Device %s is still active.\n", device_name);
    }
    else
    {
        printf("Something failed perhaps, device %s is not active.\n",
            device_name);
        crypt_free(cd);
        return -1;
    }

    r = crypt_deactivate(cd, device_name);
    if (r < 0)
    {
        printf("crypt_deactivate() failed.\n");
        crypt_free(cd);
        return r;
    }

    printf("Device %s is now deactivated.\n", device_name);
    crypt_free(cd);
    return 0;
}

/**
 * Create a new encrypted container on a given device.
 * This overwrites the current contents of the device.
 * @param path     path to the device
 * @param password password of the new container
 * @return         status code
 */
static int create_encrypted_device(const char * path, const char * password)
{
    struct crypt_device * cd;
    struct crypt_params_luks1 params;
    int r;

    r = crypt_init(&cd, path);
    if (r < 0 )
    {
        printf("crypt_init() failed for %s.\n", path);
        return r;
    }

    printf("Context is attached to block device %s.\n",
        crypt_get_device_name(cd));

    params.hash = "sha1";
    params.data_alignment = 0;
    params.data_device = NULL;
    r = crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", NULL, NULL, 256 / 8,
        &params);

    if (r < 0)
    {
        printf("crypt_format() failed on device %s\n",
            crypt_get_device_name(cd));
        crypt_free(cd);
        return r;
    }

    r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, NULL, 0, password,
        strlen(password));
    if (r < 0)
    {
        printf("Adding keyslot failed.\n");
        crypt_free(cd);
        return r;
    }
    printf("The first keyslot is initialized.\n");

    crypt_free(cd);
    return 0;
}