mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Prepare new superblock format.
This commit is contained in:
83
lib/bitops.h
Normal file
83
lib/bitops.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef BITOPS_H
|
||||
#define BITOPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Bit map related macros. Usually provided by libc.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef NBBY
|
||||
# define NBBY CHAR_BIT
|
||||
#endif
|
||||
|
||||
#ifndef setbit
|
||||
# define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
|
||||
# define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
|
||||
# define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
|
||||
# define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Byte swab macros (based on linux/byteorder/swab.h)
|
||||
*/
|
||||
#define swab16(x) \
|
||||
((uint16_t)( \
|
||||
(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
|
||||
(((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ))
|
||||
|
||||
#define swab32(x) \
|
||||
((uint32_t)( \
|
||||
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
|
||||
|
||||
#define swab64(x) \
|
||||
((uint64_t)( \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) ))
|
||||
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define cpu_to_le16(x) swab16(x)
|
||||
#define cpu_to_le32(x) swab32(x)
|
||||
#define cpu_to_le64(x) swab64(x)
|
||||
#define cpu_to_be16(x) ((uint16_t)(x))
|
||||
#define cpu_to_be32(x) ((uint32_t)(x))
|
||||
#define cpu_to_be64(x) ((uint64_t)(x))
|
||||
|
||||
#define le16_to_cpu(x) swab16(x)
|
||||
#define le32_to_cpu(x) swab32(x)
|
||||
#define le64_to_cpu(x) swab64(x)
|
||||
#define be16_to_cpu(x) ((uint16_t)(x))
|
||||
#define be32_to_cpu(x) ((uint32_t)(x))
|
||||
#define be64_to_cpu(x) ((uint64_t)(x))
|
||||
|
||||
#else /* !WORDS_BIGENDIAN */
|
||||
|
||||
#define cpu_to_le16(x) ((uint16_t)(x))
|
||||
#define cpu_to_le32(x) ((uint32_t)(x))
|
||||
#define cpu_to_le64(x) ((uint64_t)(x))
|
||||
#define cpu_to_be16(x) swab16(x)
|
||||
#define cpu_to_be32(x) swab32(x)
|
||||
#define cpu_to_be64(x) swab64(x)
|
||||
|
||||
#define le16_to_cpu(x) ((uint16_t)(x))
|
||||
#define le32_to_cpu(x) ((uint32_t)(x))
|
||||
#define le64_to_cpu(x) ((uint64_t)(x))
|
||||
#define be16_to_cpu(x) swab16(x)
|
||||
#define be32_to_cpu(x) swab32(x)
|
||||
#define be64_to_cpu(x) swab64(x)
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
#endif /* BITOPS_H */
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "nls.h"
|
||||
#include "bitops.h"
|
||||
#include "utils_crypt.h"
|
||||
#include "utils_loop.h"
|
||||
#include "utils_dm.h"
|
||||
|
||||
@@ -377,7 +377,7 @@ struct crypt_params_verity {
|
||||
uint32_t hash_block_size; /**< hash block size (in bytes) */
|
||||
uint64_t data_size; /**< data area size (in data blocks) */
|
||||
uint64_t hash_area_offset; /**< hash/header offset (in bytes) */
|
||||
uint32_t version; /**< in-kernel hash version */
|
||||
uint32_t hash_type; /**< in-kernel hashing type */
|
||||
uint32_t flags; /**< CRYPT_VERITY* flags */
|
||||
};
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@ 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,
|
||||
vp->hash_type, dmd->data_device,
|
||||
dmd->u.verity.hash_device,
|
||||
vp->data_block_size, vp->hash_block_size,
|
||||
vp->data_size, dmd->u.verity.hash_offset,
|
||||
@@ -362,7 +362,6 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
|
||||
crypt_safe_free(params);
|
||||
params = NULL;
|
||||
}
|
||||
log_dbg("TABLE: %s", params);
|
||||
out:
|
||||
crypt_safe_free(hexroot);
|
||||
crypt_safe_free(hexsalt);
|
||||
@@ -837,7 +836,7 @@ static int _dm_query_verity(uint32_t get_flags,
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->version = val32;
|
||||
vp->hash_type = val32;
|
||||
params++;
|
||||
|
||||
/* data device */
|
||||
|
||||
14
lib/setup.c
14
lib/setup.c
@@ -776,7 +776,7 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
|
||||
cd->verity_hdr.data_block_size = params.data_block_size;
|
||||
cd->verity_hdr.hash_block_size = params.hash_block_size;
|
||||
cd->verity_hdr.hash_area_offset = dmd.u.verity.hash_offset;
|
||||
cd->verity_hdr.version = params.version;
|
||||
cd->verity_hdr.hash_type = params.hash_type;
|
||||
cd->verity_hdr.flags = params.flags;
|
||||
cd->verity_hdr.salt_size = params.salt_size;
|
||||
cd->verity_hdr.salt = params.salt;
|
||||
@@ -1036,9 +1036,6 @@ static int _crypt_format_verity(struct crypt_device *cd,
|
||||
if (!params || !params->data_device)
|
||||
return -EINVAL;
|
||||
|
||||
if (params->version > 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* set data device */
|
||||
cd->type = CRYPT_VERITY;
|
||||
r = crypt_set_data_device(cd, params->data_device);
|
||||
@@ -1069,7 +1066,7 @@ static int _crypt_format_verity(struct crypt_device *cd,
|
||||
cd->verity_hdr.data_block_size = params->data_block_size;
|
||||
cd->verity_hdr.hash_block_size = params->hash_block_size;
|
||||
cd->verity_hdr.hash_area_offset = params->hash_area_offset;
|
||||
cd->verity_hdr.version = params->version;
|
||||
cd->verity_hdr.hash_type = params->hash_type;
|
||||
cd->verity_hdr.flags = params->flags;
|
||||
cd->verity_hdr.salt_size = params->salt_size;
|
||||
cd->verity_hdr.salt = malloc(params->salt_size);
|
||||
@@ -1327,7 +1324,6 @@ int crypt_header_restore(struct crypt_device *cd,
|
||||
if (requested_type && !isLUKS(requested_type))
|
||||
return -EINVAL;
|
||||
|
||||
/* Some hash functions need initialized gcrypt library */
|
||||
r = init_crypto(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1946,7 +1942,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
|
||||
struct volume_key *vk = NULL;
|
||||
int r = -EINVAL;
|
||||
|
||||
log_dbg("Activating volume %s by volume key.", name);
|
||||
log_dbg("Activating volume %s by volume key.", name ?: "[none]");
|
||||
|
||||
if (name) {
|
||||
ci = crypt_status(NULL, name);
|
||||
@@ -2255,7 +2251,7 @@ static int _luks_dump(struct crypt_device *cd)
|
||||
static int _verity_dump(struct crypt_device *cd)
|
||||
{
|
||||
log_std(cd, "VERITY header information for %s\n", mdata_device(cd));
|
||||
log_std(cd, "Version: \t%u\n", cd->verity_hdr.version);
|
||||
log_std(cd, "Hash type: \t%u\n", cd->verity_hdr.hash_type);
|
||||
log_std(cd, "Data blocks: \t%" PRIu64 "\n", cd->verity_hdr.data_size);
|
||||
log_std(cd, "Data block size: \t%u\n", cd->verity_hdr.data_block_size);
|
||||
log_std(cd, "Hash block size: \t%u\n", cd->verity_hdr.hash_block_size);
|
||||
@@ -2415,7 +2411,7 @@ int crypt_get_verity_info(struct crypt_device *cd,
|
||||
vp->hash_block_size = cd->verity_hdr.hash_block_size;
|
||||
vp->data_size = cd->verity_hdr.data_size;
|
||||
vp->hash_area_offset = cd->verity_hdr.hash_area_offset;
|
||||
vp->version = cd->verity_hdr.version;
|
||||
vp->hash_type = cd->verity_hdr.hash_type;
|
||||
vp->flags = cd->verity_hdr.flags & CRYPT_VERITY_NO_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -30,7 +31,9 @@
|
||||
#include "verity.h"
|
||||
#include "internal.h"
|
||||
|
||||
/* FIXME: not yet final on-disk format! Add UUID etc */
|
||||
#define NEW_SB 1
|
||||
|
||||
#ifndef NEW_SB
|
||||
struct verity_sb {
|
||||
uint8_t signature[8];
|
||||
uint8_t version;
|
||||
@@ -42,10 +45,26 @@ struct verity_sb {
|
||||
uint32_t data_blocks_hi;
|
||||
uint32_t data_blocks_lo;
|
||||
uint8_t algorithm[16];
|
||||
uint8_t salt[VERITY_MAX_SALT_SIZE];
|
||||
uint8_t salt[384];
|
||||
uint8_t pad3[88];
|
||||
};
|
||||
|
||||
#else
|
||||
struct verity_sb {
|
||||
uint8_t signature[8]; /* "verity\0\0" */
|
||||
uint32_t version; /* superblock version */
|
||||
uint32_t hash_type; /* 0 - Chrome OS, 1 - normal */
|
||||
uint8_t uuid[16]; /* UUID of hash device */
|
||||
uint8_t algorithm[32];/* hash algorithm name */
|
||||
uint64_t data_block_size; /* data block in bytes */
|
||||
uint64_t hash_block_size; /* hash block in bytes */
|
||||
uint64_t data_blocks; /* number of data blocks */
|
||||
uint64_t salt_size; /* salt size */
|
||||
uint8_t salt[256]; /* salt */
|
||||
uint8_t _pad[160];
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
/* Read verity superblock from disk */
|
||||
int VERITY_read_sb(struct crypt_device *cd,
|
||||
const char *device,
|
||||
@@ -54,7 +73,7 @@ int VERITY_read_sb(struct crypt_device *cd,
|
||||
{
|
||||
struct verity_sb sb = {};
|
||||
ssize_t hdr_size = sizeof(struct verity_sb);
|
||||
int devfd = 0;
|
||||
int devfd = 0, sb_version;
|
||||
uint64_t sb_data_blocks;
|
||||
|
||||
log_dbg("Reading VERITY header of size %u on device %s, offset %" PRIu64 ".",
|
||||
@@ -82,7 +101,7 @@ int VERITY_read_sb(struct crypt_device *cd,
|
||||
log_err(cd, _("Device %s is not a valid VERITY device.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifndef NEW_SB
|
||||
if (sb.version > 1) {
|
||||
log_err(cd, _("Unsupported VERITY version %d.\n"), sb.version);
|
||||
return -EINVAL;
|
||||
@@ -91,7 +110,7 @@ int VERITY_read_sb(struct crypt_device *cd,
|
||||
if (sb.data_block_bits < 9 || sb.data_block_bits >= 31 ||
|
||||
sb.hash_block_bits < 9 || sb.hash_block_bits >= 31 ||
|
||||
!memchr(sb.algorithm, 0, sizeof(sb.algorithm)) ||
|
||||
ntohs(sb.salt_size) > VERITY_MAX_SALT_SIZE) {
|
||||
ntohs(sb.salt_size) > 256) {
|
||||
log_err(cd, _("VERITY header corrupted.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -110,9 +129,46 @@ int VERITY_read_sb(struct crypt_device *cd,
|
||||
if (!params->salt)
|
||||
return -ENOMEM;
|
||||
memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
|
||||
params->hash_area_offset = sb_offset;
|
||||
params->version = sb.version;
|
||||
params->hash_type = sb.version;
|
||||
#else
|
||||
sb_version = le32_to_cpu(sb.version);
|
||||
if (sb_version != 1) {
|
||||
log_err(cd, _("Unsupported VERITY version %d.\n"), sb_version);
|
||||
return -EINVAL;
|
||||
}
|
||||
params->hash_type = le32_to_cpu(sb.hash_type);
|
||||
if (params->hash_type > 1) {
|
||||
log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
params->data_block_size = le64_to_cpu(sb.data_block_size);
|
||||
params->hash_block_size = le64_to_cpu(sb.hash_block_size);
|
||||
if (params->data_block_size % 512 || params->hash_block_size % 512) {
|
||||
log_err(cd, _("Unsupported VERITY block size.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
params->data_size = le64_to_cpu(sb.data_blocks);
|
||||
|
||||
params->hash_name = strndup((const char*)sb.algorithm, sizeof(sb.algorithm));
|
||||
if (!params->hash_name)
|
||||
return -ENOMEM;
|
||||
|
||||
params->salt_size = le64_to_cpu(sb.salt_size);
|
||||
if (params->salt_size > sizeof(sb.salt)) {
|
||||
log_err(cd, _("VERITY header corrupted.\n"));
|
||||
free(CONST_CAST(char*)params->hash_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
params->salt = malloc(params->salt_size);
|
||||
if (!params->salt) {
|
||||
free(CONST_CAST(char*)params->hash_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
|
||||
|
||||
#endif
|
||||
params->hash_area_offset = sb_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -141,7 +197,8 @@ int VERITY_write_sb(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
memcpy(&sb.signature, VERITY_SIGNATURE, sizeof(sb.signature));
|
||||
sb.version = params->version;
|
||||
#ifndef NEW_SB
|
||||
sb.version = params->hash_type;
|
||||
sb.data_block_bits = ffs(params->data_block_size) - 1;
|
||||
sb.hash_block_bits = ffs(params->hash_block_size) - 1;
|
||||
sb.salt_size = htons(params->salt_size);
|
||||
@@ -149,7 +206,16 @@ int VERITY_write_sb(struct crypt_device *cd,
|
||||
sb.data_blocks_lo = htonl(params->data_size & 0xFFFFFFFF);
|
||||
strncpy((char *)sb.algorithm, params->hash_name, sizeof(sb.algorithm));
|
||||
memcpy(sb.salt, params->salt, params->salt_size);
|
||||
|
||||
#else
|
||||
sb.version = cpu_to_le32(1);
|
||||
sb.hash_type = cpu_to_le32(params->hash_type);
|
||||
sb.data_block_size = cpu_to_le64(params->data_block_size);
|
||||
sb.hash_block_size = cpu_to_le64(params->hash_block_size);
|
||||
sb.salt_size = cpu_to_le64(params->salt_size);
|
||||
sb.data_blocks = cpu_to_le64(params->data_size);
|
||||
strncpy((char *)sb.algorithm, params->hash_name, sizeof(sb.algorithm));
|
||||
memcpy(sb.salt, params->salt, params->salt_size);
|
||||
#endif
|
||||
r = write_lseek_blockwise(devfd, (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0;
|
||||
if (r)
|
||||
log_err(cd, _("Error during update of verity header on device %s.\n"), device);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#define VERITY_SIGNATURE "verity\0\0"
|
||||
#define VERITY_MAX_LEVELS 63
|
||||
#define VERITY_MAX_SALT_SIZE 384
|
||||
|
||||
struct crypt_device;
|
||||
struct crypt_params_verity;
|
||||
|
||||
@@ -324,7 +324,7 @@ int VERITY_verify(struct crypt_device *cd,
|
||||
size_t root_hash_size)
|
||||
{
|
||||
return VERITY_create_or_verify_hash(cd, 1,
|
||||
verity_hdr->version,
|
||||
verity_hdr->hash_type,
|
||||
verity_hdr->hash_name,
|
||||
hash_device,
|
||||
data_device,
|
||||
@@ -348,7 +348,7 @@ int VERITY_create(struct crypt_device *cd,
|
||||
{
|
||||
int pgsize = crypt_getpagesize();
|
||||
|
||||
if (verity_hdr->salt_size > VERITY_MAX_SALT_SIZE)
|
||||
if (verity_hdr->salt_size > 256)
|
||||
return -EINVAL;
|
||||
|
||||
if (verity_hdr->hash_block_size > pgsize ||
|
||||
@@ -357,7 +357,7 @@ int VERITY_create(struct crypt_device *cd,
|
||||
"size exceeds page size (%u).\n"), pgsize);
|
||||
|
||||
return VERITY_create_or_verify_hash(cd, 0,
|
||||
verity_hdr->version,
|
||||
verity_hdr->hash_type,
|
||||
verity_hdr->hash_name,
|
||||
hash_device,
|
||||
data_device,
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
/* TODO:
|
||||
* - extend superblock (UUID)
|
||||
* - add api tests
|
||||
* - report in-kernel status outside libcryptsetup (extend api)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -40,7 +39,7 @@
|
||||
static int use_superblock = 1; /* FIXME: no superblock not supported */
|
||||
|
||||
static const char *hash_algorithm = NULL;
|
||||
static int version = 1;
|
||||
static int hash_type = 1;
|
||||
static int data_block_size = DEFAULT_VERITY_DATA_BLOCK;
|
||||
static int hash_block_size = DEFAULT_VERITY_HASH_BLOCK;
|
||||
static uint64_t data_blocks = 0;
|
||||
@@ -142,7 +141,7 @@ static int _prepare_format(struct crypt_params_verity *params,
|
||||
params->hash_block_size = hash_block_size;
|
||||
params->data_size = data_blocks;
|
||||
params->hash_area_offset = hash_start;
|
||||
params->version = version;
|
||||
params->hash_type = hash_type;
|
||||
params->flags = flags;
|
||||
|
||||
return 0;
|
||||
@@ -300,7 +299,7 @@ static int action_status(int arg)
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
log_std(" version: %u\n", vp.version);
|
||||
log_std(" hash type: %u\n", vp.hash_type);
|
||||
log_std(" data block: %u\n", vp.data_block_size);
|
||||
log_std(" hash block: %u\n", vp.hash_block_size);
|
||||
log_std(" hash name: %s\n", vp.hash_name);
|
||||
@@ -499,7 +498,7 @@ int main(int argc, const char **argv)
|
||||
{ "verbose", 'v', POPT_ARG_NONE, &opt_verbose, 0, N_("Shows more detailed error messages"), NULL },
|
||||
{ "debug", '\0', POPT_ARG_NONE, &opt_debug, 0, N_("Show debug messages"), NULL },
|
||||
{ "no-superblock", 0, POPT_ARG_VAL, &use_superblock, 0, N_("Do not use verity superblock"), NULL },
|
||||
{ "format", 0, POPT_ARG_INT, &version, 0, N_("Format type (1 - normal, 0 - original Chromium OS)"), N_("number") },
|
||||
{ "format", 0, POPT_ARG_INT, &hash_type, 0, N_("Format type (1 - normal, 0 - original Chrome OS)"), N_("number") },
|
||||
{ "data-block-size", 0, POPT_ARG_INT, &data_block_size, 0, N_("Block size on the data device"), N_("bytes") },
|
||||
{ "hash-block-size", 0, POPT_ARG_INT, &hash_block_size, 0, N_("Block size on the hash device"), N_("bytes") },
|
||||
{ "data-blocks", 0, POPT_ARG_STRING, &popt_tmp, 1, N_("The number of blocks in the data file"), N_("blocks") },
|
||||
|
||||
Reference in New Issue
Block a user