* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
- * Copyright (C) 2014-2020 Milan Broz
+ * Copyright (C) 2014-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
/* Block encryption storage context */
struct crypt_storage {
- unsigned sector_shift;
+ size_t sector_size;
unsigned iv_shift;
struct crypt_cipher *cipher;
struct crypt_sector_iv cipher_iv;
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
const char *cipher_name, const char *mode_name,
- const char *iv_name, const void *key, size_t key_length, size_t sector_size)
+ const char *iv_name, const void *key, size_t key_length,
+ size_t sector_size)
{
int r;
memset(ctx, 0, sizeof(*ctx));
ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
- if (ctx->iv_size < 8)
+ if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
return -ENOENT;
if (!strcmp(cipher_name, "cipher_null") ||
size_t sector_size,
const char *cipher,
const char *cipher_mode,
- const void *key, size_t key_length)
+ const void *key, size_t key_length,
+ bool large_iv)
{
struct crypt_storage *s;
char mode_name[64];
return r;
}
- s->sector_shift = int_log2(sector_size);
- s->iv_shift = s->sector_shift - SECTOR_SHIFT;
+ s->sector_size = sector_size;
+ s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
*ctx = s;
return 0;
uint64_t i;
int r = 0;
- if (length & ((1 << ctx->sector_shift) - 1))
+ if (length & (ctx->sector_size - 1))
return -EINVAL;
- length >>= ctx->sector_shift;
+ if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
+ return -EINVAL;
- for (i = 0; i < length; i++) {
- r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (uint64_t)(i << ctx->iv_shift));
+ for (i = 0; i < length; i += ctx->sector_size) {
+ r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
if (r)
break;
r = crypt_cipher_decrypt(ctx->cipher,
- &buffer[i << ctx->sector_shift],
- &buffer[i << ctx->sector_shift],
- 1 << ctx->sector_shift,
+ &buffer[i],
+ &buffer[i],
+ ctx->sector_size,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)
uint64_t i;
int r = 0;
- if (length & ((1 << ctx->sector_shift) - 1))
+ if (length & (ctx->sector_size - 1))
return -EINVAL;
- length >>= ctx->sector_shift;
+ if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
+ return -EINVAL;
- for (i = 0; i < length; i++) {
- r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (i << ctx->iv_shift));
+ for (i = 0; i < length; i += ctx->sector_size) {
+ r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
if (r)
break;
r = crypt_cipher_encrypt(ctx->cipher,
- &buffer[i << ctx->sector_shift],
- &buffer[i << ctx->sector_shift],
- 1 << ctx->sector_shift,
+ &buffer[i],
+ &buffer[i],
+ ctx->sector_size,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)