diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h index 711c81e4..e316808d 100644 --- a/lib/crypto_backend/crypto_backend.h +++ b/lib/crypto_backend/crypto_backend.h @@ -108,14 +108,14 @@ int crypt_cipher_check_kernel(const char *name, const char *mode, const char *integrity, size_t key_length); /* Storage encryption wrappers */ -int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start, +int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size, const char *cipher, const char *cipher_mode, const void *key, size_t key_length); void crypt_storage_destroy(struct crypt_storage *ctx); -int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector, - size_t count, char *buffer); -int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector, - size_t count, char *buffer); +int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset, + uint64_t length, char *buffer); +int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset, + uint64_t length, char *buffer); /* Memzero helper (memset on stack can be optimized out) */ static inline void crypt_backend_memzero(void *s, size_t n) diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c index 16a20b1d..363d55d1 100644 --- a/lib/crypto_backend/crypto_storage.c +++ b/lib/crypto_backend/crypto_storage.c @@ -25,7 +25,6 @@ #include "crypto_backend.h" #define SECTOR_SHIFT 9 -#define SECTOR_SIZE (1 << SECTOR_SHIFT) /* * Internal IV helper @@ -41,7 +40,8 @@ struct crypt_sector_iv { /* Block encryption storage context */ struct crypt_storage { - uint64_t sector_start; + unsigned sector_shift; + unsigned iv_shift; struct crypt_cipher *cipher; struct crypt_sector_iv cipher_iv; }; @@ -194,7 +194,7 @@ static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx) /* Block encryption storage wrappers */ int crypt_storage_init(struct crypt_storage **ctx, - uint64_t sector_start, + size_t sector_size, const char *cipher, const char *cipher_mode, const void *key, size_t key_length) @@ -204,6 +204,11 @@ int crypt_storage_init(struct crypt_storage **ctx, char *cipher_iv = NULL; int r = -EIO; + if (sector_size < (1 << SECTOR_SHIFT) || + sector_size > (1 << (SECTOR_SHIFT + 3)) || + sector_size & (sector_size - 1)) + return -EINVAL; + s = malloc(sizeof(*s)); if (!s) return -ENOMEM; @@ -230,27 +235,33 @@ int crypt_storage_init(struct crypt_storage **ctx, return r; } - s->sector_start = sector_start; + s->sector_shift = int_log2(sector_size); + s->iv_shift = s->sector_shift - SECTOR_SHIFT; *ctx = s; return 0; } int crypt_storage_decrypt(struct crypt_storage *ctx, - uint64_t sector, size_t count, - char *buffer) + uint64_t iv_offset, + uint64_t length, char *buffer) { unsigned int i; int r = 0; - for (i = 0; i < count; i++) { - r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i); + if (length & ((1 << ctx->sector_shift) - 1)) + return -EINVAL; + + length >>= ctx->sector_shift; + + for (i = 0; i < length; i++) { + r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (uint64_t)(i << ctx->iv_shift)); if (r) break; r = crypt_cipher_decrypt(ctx->cipher, - &buffer[i * SECTOR_SIZE], - &buffer[i * SECTOR_SIZE], - SECTOR_SIZE, + &buffer[i << ctx->sector_shift], + &buffer[i << ctx->sector_shift], + 1 << ctx->sector_shift, ctx->cipher_iv.iv, ctx->cipher_iv.iv_size); if (r) @@ -261,20 +272,25 @@ int crypt_storage_decrypt(struct crypt_storage *ctx, } int crypt_storage_encrypt(struct crypt_storage *ctx, - uint64_t sector, size_t count, - char *buffer) + uint64_t iv_offset, + uint64_t length, char *buffer) { unsigned int i; int r = 0; - for (i = 0; i < count; i++) { - r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i); + if (length & ((1 << ctx->sector_shift) - 1)) + return -EINVAL; + + length >>= ctx->sector_shift; + + for (i = 0; i < length; i++) { + r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (i << ctx->iv_shift)); if (r) break; r = crypt_cipher_encrypt(ctx->cipher, - &buffer[i * SECTOR_SIZE], - &buffer[i * SECTOR_SIZE], - SECTOR_SIZE, + &buffer[i << ctx->sector_shift], + &buffer[i << ctx->sector_shift], + 1 << ctx->sector_shift, ctx->cipher_iv.iv, ctx->cipher_iv.iv_size); if (r) diff --git a/lib/luks1/keyencryption.c b/lib/luks1/keyencryption.c index 9a024d2f..55da7885 100644 --- a/lib/luks1/keyencryption.c +++ b/lib/luks1/keyencryption.c @@ -153,7 +153,7 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength, return -EINVAL; /* Encrypt buffer */ - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).", @@ -172,7 +172,7 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength, log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area."); - r = crypt_storage_encrypt(s, 0, srcLength / SECTOR_SIZE, src); + r = crypt_storage_encrypt(s, 0, srcLength, src); crypt_storage_destroy(s); if (r) @@ -221,7 +221,7 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength, if (MISALIGNED_512(dstLength)) return -EINVAL; - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).", @@ -267,7 +267,7 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength, close(devfd); /* Decrypt buffer */ - r = crypt_storage_decrypt(s, 0, dstLength / SECTOR_SIZE, dst); + r = crypt_storage_decrypt(s, 0, dstLength, dst); crypt_storage_destroy(s); return r; diff --git a/lib/luks2/luks2_keyslot_luks2.c b/lib/luks2/luks2_keyslot_luks2.c index 26fe9b18..10f72378 100644 --- a/lib/luks2/luks2_keyslot_luks2.c +++ b/lib/luks2/luks2_keyslot_luks2.c @@ -52,14 +52,14 @@ static int luks2_encrypt_to_storage(char *src, size_t srcLength, return -EINVAL; /* Encrypt buffer */ - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) { log_dbg(cd, "Userspace crypto wrapper cannot use %s-%s (%d).", cipher, cipher_mode, r); return r; } - r = crypt_storage_encrypt(s, 0, srcLength / SECTOR_SIZE, src); + r = crypt_storage_encrypt(s, 0, srcLength, src); crypt_storage_destroy(s); if (r) return r; @@ -116,7 +116,7 @@ static int luks2_decrypt_from_storage(char *dst, size_t dstLength, if (MISALIGNED_512(dstLength)) return -EINVAL; - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) { log_dbg(cd, "Userspace crypto wrapper cannot use %s-%s (%d).", cipher, cipher_mode, r); @@ -147,7 +147,7 @@ static int luks2_decrypt_from_storage(char *dst, size_t dstLength, /* Decrypt buffer */ if (!r) - r = crypt_storage_decrypt(s, 0, dstLength / SECTOR_SIZE, dst); + r = crypt_storage_decrypt(s, 0, dstLength, dst); else log_err(cd, _("IO error while decrypting keyslot."));