"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/verity/verity_hash.c" between
cryptsetup-2.3.6.tar.xz and cryptsetup-2.4.0.tar.xz

About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.

verity_hash.c  (cryptsetup-2.3.6.tar.xz):verity_hash.c  (cryptsetup-2.4.0.tar.xz)
skipping to change at line 31 skipping to change at line 31
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include "verity.h" #include "verity.h"
#include "internal.h" #include "internal.h"
#define VERITY_MAX_LEVELS 63 #define VERITY_MAX_LEVELS 63
#define VERITY_MAX_DIGEST_SIZE 1024
static unsigned get_bits_up(size_t u) static unsigned get_bits_up(size_t u)
{ {
unsigned i = 0; unsigned i = 0;
while ((1U << i) < u) while ((1U << i) < u)
i++; i++;
return i; return i;
} }
static unsigned get_bits_down(size_t u) static unsigned get_bits_down(size_t u)
{ {
unsigned i = 0; unsigned i = 0;
while ((u >> i) > 1U) while ((u >> i) > 1U)
i++; i++;
return i; return i;
} }
static int verify_zero(struct crypt_device *cd, FILE *wr, size_t bytes) static int verify_zero(struct crypt_device *cd, FILE *wr, size_t bytes)
{ {
char block[bytes]; char *block = NULL;
size_t i; size_t i;
int r;
block = malloc(bytes);
if (!block)
return -ENOMEM;
if (fread(block, bytes, 1, wr) != 1) { if (fread(block, bytes, 1, wr) != 1) {
log_dbg(cd, "EIO while reading spare area."); log_dbg(cd, "EIO while reading spare area.");
return -EIO; r = -EIO;
goto out;
} }
for (i = 0; i < bytes; i++) for (i = 0; i < bytes; i++)
if (block[i]) { if (block[i]) {
log_err(cd, _("Spare area is not zeroed at position %" PR Iu64 "."), log_err(cd, _("Spare area is not zeroed at position %" PR Iu64 "."),
ftello(wr) - bytes); ftello(wr) - bytes);
return -EPERM; r = -EPERM;
goto out;
} }
return 0; r = 0;
out:
free(block);
return r;
} }
static int verify_hash_block(const char *hash_name, int version, static int verify_hash_block(const char *hash_name, int version,
char *hash, size_t hash_size, char *hash, size_t hash_size,
const char *data, size_t data_size, const char *data, size_t data_size,
const char *salt, size_t salt_size) const char *salt, size_t salt_size)
{ {
struct crypt_hash *ctx = NULL; struct crypt_hash *ctx = NULL;
int r; int r;
skipping to change at line 141 skipping to change at line 152
} }
static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr,
uint64_t data_block, size_t data_block_size, uint64_t data_block, size_t data_block_size,
uint64_t hash_block, size_t hash_block_size, uint64_t hash_block, size_t hash_block_size,
uint64_t blocks, int version, uint64_t blocks, int version,
const char *hash_name, int verify, const char *hash_name, int verify,
char *calculated_digest, size_t digest_size, char *calculated_digest, size_t digest_size,
const char *salt, size_t salt_size) const char *salt, size_t salt_size)
{ {
char left_block[hash_block_size]; char *left_block, *data_buffer;
char data_buffer[data_block_size]; char read_digest[VERITY_MAX_DIGEST_SIZE];
char read_digest[digest_size];
size_t hash_per_block = 1 << get_bits_down(hash_block_size / digest_size) ; size_t hash_per_block = 1 << get_bits_down(hash_block_size / digest_size) ;
size_t digest_size_full = 1 << get_bits_up(digest_size); size_t digest_size_full = 1 << get_bits_up(digest_size);
uint64_t blocks_to_write = (blocks + hash_per_block - 1) / hash_per_block ; uint64_t blocks_to_write = (blocks + hash_per_block - 1) / hash_per_block ;
uint64_t seek_rd, seek_wr; uint64_t seek_rd, seek_wr;
size_t left_bytes; size_t left_bytes;
unsigned i; unsigned i;
int r; int r;
if (digest_size > sizeof(read_digest))
return -EINVAL;
if (uint64_mult_overflow(&seek_rd, data_block, data_block_size) || if (uint64_mult_overflow(&seek_rd, data_block, data_block_size) ||
uint64_mult_overflow(&seek_wr, hash_block, hash_block_size)) { uint64_mult_overflow(&seek_wr, hash_block, hash_block_size)) {
log_err(cd, _("Device offset overflow.")); log_err(cd, _("Device offset overflow."));
return -EINVAL; return -EINVAL;
} }
if (fseeko(rd, seek_rd, SEEK_SET)) { if (fseeko(rd, seek_rd, SEEK_SET)) {
log_dbg(cd, "Cannot seek to requested position in data device."); log_dbg(cd, "Cannot seek to requested position in data device.");
return -EIO; return -EIO;
} }
if (wr && fseeko(wr, seek_wr, SEEK_SET)) { if (wr && fseeko(wr, seek_wr, SEEK_SET)) {
log_dbg(cd, "Cannot seek to requested position in hash device."); log_dbg(cd, "Cannot seek to requested position in hash device.");
return -EIO; return -EIO;
} }
left_block = malloc(hash_block_size);
data_buffer = malloc(data_block_size);
if (!left_block || !data_buffer) {
r = -ENOMEM;
goto out;
}
memset(left_block, 0, hash_block_size); memset(left_block, 0, hash_block_size);
while (blocks_to_write--) { while (blocks_to_write--) {
left_bytes = hash_block_size; left_bytes = hash_block_size;
for (i = 0; i < hash_per_block; i++) { for (i = 0; i < hash_per_block; i++) {
if (!blocks) if (!blocks)
break; break;
blocks--; blocks--;
if (fread(data_buffer, data_block_size, 1, rd) != 1) { if (fread(data_buffer, data_block_size, 1, rd) != 1) {
log_dbg(cd, "Cannot read data device block."); log_dbg(cd, "Cannot read data device block.");
return -EIO; r = -EIO;
goto out;
} }
if (verify_hash_block(hash_name, version, if (verify_hash_block(hash_name, version,
calculated_digest, digest_size, calculated_digest, digest_size,
data_buffer, data_block_size, data_buffer, data_block_size,
salt, salt_size)) salt, salt_size)) {
return -EINVAL; r = -EINVAL;
goto out;
}
if (!wr) if (!wr)
break; break;
if (verify) { if (verify) {
if (fread(read_digest, digest_size, 1, wr) != 1) { if (fread(read_digest, digest_size, 1, wr) != 1) {
log_dbg(cd, "Cannot read digest form hash device."); log_dbg(cd, "Cannot read digest form hash device.");
return -EIO; r = -EIO;
goto out;
} }
if (memcmp(read_digest, calculated_digest, digest _size)) { if (memcmp(read_digest, calculated_digest, digest _size)) {
log_err(cd, _("Verification failed at pos ition %" PRIu64 "."), log_err(cd, _("Verification failed at pos ition %" PRIu64 "."),
ftello(rd) - data_block_size); ftello(rd) - data_block_size);
return -EPERM; r = -EPERM;
goto out;
} }
} else { } else {
if (fwrite(calculated_digest, digest_size, 1, wr) != 1) { if (fwrite(calculated_digest, digest_size, 1, wr) != 1) {
log_dbg(cd, "Cannot write digest to hash device."); log_dbg(cd, "Cannot write digest to hash device.");
return -EIO; r = -EIO;
goto out;
} }
} }
if (version == 0) { if (version == 0) {
left_bytes -= digest_size; left_bytes -= digest_size;
} else { } else {
if (digest_size_full - digest_size) { if (digest_size_full - digest_size) {
if (verify) { if (verify) {
r = verify_zero(cd, wr, digest_si ze_full - digest_size); r = verify_zero(cd, wr, digest_si ze_full - digest_size);
if (r) if (r)
return r; goto out;
} else if (fwrite(left_block, digest_size _full - digest_size, 1, wr) != 1) { } else if (fwrite(left_block, digest_size _full - digest_size, 1, wr) != 1) {
log_dbg(cd, "Cannot write spare a rea to hash device."); log_dbg(cd, "Cannot write spare a rea to hash device.");
return -EIO; r = -EIO;
goto out;
} }
} }
left_bytes -= digest_size_full; left_bytes -= digest_size_full;
} }
} }
if (wr && left_bytes) { if (wr && left_bytes) {
if (verify) { if (verify) {
r = verify_zero(cd , wr, left_bytes); r = verify_zero(cd , wr, left_bytes);
if (r) if (r)
return r; goto out;
} else if (fwrite(left_block, left_bytes, 1, wr) != 1) { } else if (fwrite(left_block, left_bytes, 1, wr) != 1) {
log_dbg(cd, "Cannot write remaining spare area to hash device."); log_dbg(cd, "Cannot write remaining spare area to hash device.");
return -EIO; r = -EIO;
goto out;
} }
} }
} }
r = 0;
return 0; out:
free(left_block);
free(data_buffer);
return r;
} }
static int VERITY_create_or_verify_hash(struct crypt_device *cd, bool verify, static int VERITY_create_or_verify_hash(struct crypt_device *cd, bool verify,
struct crypt_params_verity *params, struct crypt_params_verity *params,
char *root_hash, size_t digest_size) char *root_hash, size_t digest_size)
{ {
char calculated_digest[digest_size]; char calculated_digest[VERITY_MAX_DIGEST_SIZE];
FILE *data_file = NULL; FILE *data_file = NULL;
FILE *hash_file = NULL, *hash_file_2; FILE *hash_file = NULL, *hash_file_2;
uint64_t hash_level_block[VERITY_MAX_LEVELS]; uint64_t hash_level_block[VERITY_MAX_LEVELS];
uint64_t hash_level_size[VERITY_MAX_LEVELS]; uint64_t hash_level_size[VERITY_MAX_LEVELS];
uint64_t data_file_blocks; uint64_t data_file_blocks;
uint64_t data_device_offset_max = 0, hash_device_offset_max = 0; uint64_t data_device_offset_max = 0, hash_device_offset_max = 0;
uint64_t hash_position = VERITY_hash_offset_block(params); uint64_t hash_position = VERITY_hash_offset_block(params);
uint64_t dev_size; uint64_t dev_size;
int levels, i, r; int levels, i, r;
log_dbg(cd, "Hash %s %s, data device %s, data blocks %" PRIu64 log_dbg(cd, "Hash %s %s, data device %s, data blocks %" PRIu64
", hash_device %s, offset %" PRIu64 ".", ", hash_device %s, offset %" PRIu64 ".",
verify ? "verification" : "creation", params->hash_name, verify ? "verification" : "creation", params->hash_name,
device_path(crypt_data_device(cd)), params->data_size, device_path(crypt_data_device(cd)), params->data_size,
device_path(crypt_metadata_device(cd)), hash_position); device_path(crypt_metadata_device(cd)), hash_position);
if (digest_size > sizeof(calculated_digest))
return -EINVAL;
if (!params->data_size) { if (!params->data_size) {
r = device_size(crypt_data_device(cd), &dev_size); r = device_size(crypt_data_device(cd), &dev_size);
if (r < 0) if (r < 0)
return r; return r;
data_file_blocks = dev_size / params->data_block_size; data_file_blocks = dev_size / params->data_block_size;
} else } else
data_file_blocks = params->data_size; data_file_blocks = params->data_size;
if (uint64_mult_overflow(&data_device_offset_max, params->data_size, para ms->data_block_size)) { if (uint64_mult_overflow(&data_device_offset_max, params->data_size, para ms->data_block_size)) {
 End of changes. 21 change blocks. 
20 lines changed or deleted 54 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)