From e2375c8368d832c72ce6bd5bd0c73ee99ddc0856 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sat, 9 Jun 2012 23:20:43 +0200 Subject: [PATCH] Add verity uuid specification. --- lib/setup.c | 36 +++++++++++++++++++++++------------- lib/verity/verity.c | 25 ++++++++++++++++++++++++- lib/verity/verity.h | 4 ++++ man/veritysetup.8 | 23 +++++++++++++++-------- src/veritysetup.c | 9 +++------ 5 files changed, 69 insertions(+), 28 deletions(-) diff --git a/lib/setup.c b/lib/setup.c index 5d62f60..bcd22df 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -69,6 +69,7 @@ struct crypt_device { struct crypt_params_verity verity_hdr; char *verity_root_hash; uint64_t verity_root_hash_size; + char *verity_uuid; /* callbacks definitions */ void (*log)(int level, const char *msg, void *usrptr); @@ -660,7 +661,8 @@ static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verit if (params) sb_offset = params->hash_area_offset; - r = VERITY_read_sb(cd, mdata_device(cd), sb_offset, &cd->verity_hdr); + r = VERITY_read_sb(cd, mdata_device(cd), sb_offset, + &cd->verity_uuid, &cd->verity_hdr); if (r < 0) return r; @@ -765,8 +767,8 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name) goto out; if (isVERITY(cd->type)) { + cd->verity_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL; cd->verity_hdr.flags = CRYPT_VERITY_NO_HEADER; //FIXME - //cd->verity_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL; cd->verity_hdr.data_size = params.data_size; cd->verity_root_hash_size = dmd.u.verity.root_hash_size; cd->verity_root_hash = NULL; @@ -1023,6 +1025,7 @@ static int _crypt_format_loopaes(struct crypt_device *cd, } static int _crypt_format_verity(struct crypt_device *cd, + const char *uuid, struct crypt_params_verity *params) { int r = 0; @@ -1051,7 +1054,6 @@ static int _crypt_format_verity(struct crypt_device *cd, } else cd->verity_hdr.data_size = params->data_size; - cd->verity_root_hash_size = crypt_hash_size(params->hash_name); if (!cd->verity_root_hash_size) return -EINVAL; @@ -1077,26 +1079,29 @@ static int _crypt_format_verity(struct crypt_device *cd, r = crypt_random_get(cd, CONST_CAST(char*)cd->verity_hdr.salt, params->salt_size, CRYPT_RND_SALT); if (r) - goto out; + return r; if (params->flags & CRYPT_VERITY_CREATE_HASH) { r = VERITY_create(cd, &cd->verity_hdr, cd->device, mdata_device(cd), cd->verity_root_hash, cd->verity_root_hash_size); if (r) - goto out; + return r; } - if (!(params->flags & CRYPT_VERITY_NO_HEADER)) + if (!(params->flags & CRYPT_VERITY_NO_HEADER)) { + if (uuid) + cd->verity_uuid = strdup(uuid); + else { + r = VERITY_UUID_generate(cd, &cd->verity_uuid); + if (r) + return r; + } + r = VERITY_write_sb(cd, mdata_device(cd), cd->verity_hdr.hash_area_offset, + cd->verity_uuid, &cd->verity_hdr); -out: - if (r) { - free(cd->verity_root_hash); - free(CONST_CAST(char*)cd->verity_hdr.hash_name); - free(CONST_CAST(char*)cd->verity_hdr.salt); } - return r; } @@ -1134,7 +1139,7 @@ int crypt_format(struct crypt_device *cd, else if (isLOOPAES(type)) r = _crypt_format_loopaes(cd, cipher, uuid, volume_key_size, params); else if (isVERITY(type)) - r = _crypt_format_verity(cd, params); + r = _crypt_format_verity(cd, uuid, params); else { /* FIXME: allow plugins here? */ log_err(cd, _("Unknown crypt device type %s requested.\n"), type); @@ -1365,6 +1370,7 @@ void crypt_free(struct crypt_device *cd) free(CONST_CAST(void*)cd->verity_hdr.hash_name); free(CONST_CAST(void*)cd->verity_hdr.salt); free(cd->verity_root_hash); + free(cd->verity_uuid); free(cd); } @@ -2251,6 +2257,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, "UUID: \t%s\n", cd->verity_uuid ?: ""); 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); @@ -2320,6 +2327,9 @@ const char *crypt_get_uuid(struct crypt_device *cd) if (isLOOPAES(cd->type)) return cd->loopaes_uuid; + if (isVERITY(cd->type)) + return cd->verity_uuid; + return NULL; } diff --git a/lib/verity/verity.c b/lib/verity/verity.c index 5e0860e..7cfb811 100644 --- a/lib/verity/verity.c +++ b/lib/verity/verity.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "libcryptsetup.h" #include "verity.h" @@ -69,6 +70,7 @@ struct verity_sb { int VERITY_read_sb(struct crypt_device *cd, const char *device, uint64_t sb_offset, + char **uuid_string, struct crypt_params_verity *params) { struct verity_sb sb = {}; @@ -167,6 +169,8 @@ int VERITY_read_sb(struct crypt_device *cd, } memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size); + if ((*uuid_string = malloc(40))) + uuid_unparse(sb.uuid, *uuid_string); #endif params->hash_area_offset = sb_offset; return 0; @@ -176,15 +180,22 @@ int VERITY_read_sb(struct crypt_device *cd, int VERITY_write_sb(struct crypt_device *cd, const char *device, uint64_t sb_offset, + const char *uuid_string, struct crypt_params_verity *params) { struct verity_sb sb = {}; ssize_t hdr_size = sizeof(struct verity_sb); + uuid_t uuid; int r, devfd = 0; log_dbg("Updating VERITY header of size %u on device %s, offset %" PRIu64 ".", sizeof(struct verity_sb), device, sb_offset); + if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) { + log_err(cd, _("Wrong VERITY UUID format provided.\n"), device); + return -EINVAL; + } + if (params->flags & CRYPT_VERITY_NO_HEADER) { log_err(cd, _("Verity device doesn't use on-disk header.\n"), device); return -EINVAL; @@ -215,6 +226,7 @@ int VERITY_write_sb(struct crypt_device *cd, 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); + memcpy(sb.uuid, uuid, sizeof(sb.uuid)); #endif r = write_lseek_blockwise(devfd, (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0; if (r) @@ -238,6 +250,17 @@ uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params) return hash_offset / params->hash_block_size; } +int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string) +{ + uuid_t uuid; + + if (!(*uuid_string = malloc(40))) + return -ENOMEM; + uuid_generate(uuid); + uuid_unparse(uuid, *uuid_string); + return 0; +} + /* Activate verity device in kernel device-mapper */ int VERITY_activate(struct crypt_device *cd, const char *name, @@ -273,7 +296,7 @@ int VERITY_activate(struct crypt_device *cd, dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr), dmd.flags = activation_flags; dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512; - dmd.uuid = NULL; + dmd.uuid = crypt_get_uuid(cd); dmd.u.verity.vp = verity_hdr; r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL, diff --git a/lib/verity/verity.h b/lib/verity/verity.h index 67a8ad6..273739b 100644 --- a/lib/verity/verity.h +++ b/lib/verity/verity.h @@ -32,11 +32,13 @@ struct crypt_params_verity; int VERITY_read_sb(struct crypt_device *cd, const char *device, uint64_t sb_offset, + char **uuid, struct crypt_params_verity *params); int VERITY_write_sb(struct crypt_device *cd, const char *device, uint64_t sb_offset, + const char *uuid_string, struct crypt_params_verity *params); int VERITY_activate(struct crypt_device *cd, @@ -63,4 +65,6 @@ int VERITY_create(struct crypt_device *cd, uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params); +int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string); + #endif diff --git a/man/veritysetup.8 b/man/veritysetup.8 index 066c486..1aee3cf 100644 --- a/man/veritysetup.8 +++ b/man/veritysetup.8 @@ -24,7 +24,7 @@ or activation. This hash must be trusted. \fB\fR can be [\-\-hash, \-\-no-superblock, \-\-format, \-\-data-block-size, \-\-hash-block-size, \-\-data-blocks, \-\-hash-start, -\-\-salt] +\-\-salt, \-\-uuid] .PP \fIcreate\fR .IP @@ -59,32 +59,39 @@ Print more information on command execution. Run in debug mode with full diagnostic logs. Debug output lines are always prefixed by '#'. .TP -.B "\-\-no-superblock +.B "\-\-no-superblock" Create or use dm-verity without permanent on-disk superblock. .TP -.B "\-\-format=number +.B "\-\-format=number" Specifies the hash version type. Format type 0 is original Chrome OS verion. Format type 1 si default. .TP -.B "\-\-data-block-size=bytes +.B "\-\-data-block-size=bytes" Used block size for the data device. (Note kernel supports only page-size as maximum here.) .TP -.B "\-\-hash-block-size=bytes +.B "\-\-hash-block-size=bytes" Used block size for the hash device. (Note kernel supports only page-size as maximum here.) .TP -.B "\-\-data-blocks=blocks +.B "\-\-data-blocks=blocks" Size of data device used in verification. If not specified, the whole device is used. .TP -.B "\-\-hash-start=512-bytes sectors +.B "\-\-hash-start=512-bytes sectors" Offset of hash area/superblock on hash_device. .TP -.B "\-\-salt=hex string +.B "\-\-salt=hex string" Salt used for format or verification. Format is hexadecimal string. .TP +.B "\-\-uuid=UUID" +Use the provided UUID for the format command +instead of generating new one. + +The UUID must be provided in the standard UUID format, +e.g. 12345678-1234-1234-1234-123456789abc. +.TP .B "\-\-version" Show the program version. .SH RETURN CODES diff --git a/src/veritysetup.c b/src/veritysetup.c index 619fa19..eb5ec0d 100644 --- a/src/veritysetup.c +++ b/src/veritysetup.c @@ -17,11 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* TODO: - * - extend superblock (UUID) - * - add api tests - */ - #include #include #include @@ -45,6 +40,7 @@ static int hash_block_size = DEFAULT_VERITY_HASH_BLOCK; static uint64_t data_blocks = 0; static const char *salt_string = NULL; static uint64_t hash_start = 0; +static const char *opt_uuid = NULL; static int opt_verbose = 0; static int opt_debug = 0; @@ -164,7 +160,7 @@ static int action_format(int arg) if (r < 0) goto out; - r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms); + r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, opt_uuid, NULL, 0, ¶ms); if (!r) crypt_dump(cd); out: @@ -505,6 +501,7 @@ int main(int argc, const char **argv) { "hash-start", 0, POPT_ARG_STRING, &popt_tmp, 2, N_("Starting block on the hash device"), N_("512-byte sectors") }, { "hash", 'h', POPT_ARG_STRING, &hash_algorithm, 0, N_("Hash algorithm"), N_("string") }, { "salt", 's', POPT_ARG_STRING, &salt_string, 0, N_("Salt"), N_("hex string") }, + { "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL }, POPT_TABLEEND }; -- 2.7.4