diff --git a/lib/luks2/luks2.h b/lib/luks2/luks2.h index edec73b4..734b6997 100644 --- a/lib/luks2/luks2.h +++ b/lib/luks2/luks2.h @@ -43,8 +43,6 @@ #define LUKS2_DIGEST_MAX 8 -typedef int digests_t[LUKS2_DIGEST_MAX]; - #define CRYPT_ANY_SEGMENT -1 #define CRYPT_DEFAULT_SEGMENT 0 #define CRYPT_DEFAULT_SEGMENT_STR "0" @@ -227,16 +225,14 @@ int LUKS2_token_open_and_activate_any(struct crypt_device *cd, /* * Generic LUKS2 digest */ -int LUKS2_digests_by_segment(struct crypt_device *cd, +int LUKS2_digest_by_segment(struct crypt_device *cd, struct luks2_hdr *hdr, - int segment, - digests_t digests); + int segment); -int LUKS2_digests_verify_by_segment(struct crypt_device *cd, +int LUKS2_digest_verify_by_segment(struct crypt_device *cd, struct luks2_hdr *hdr, int segment, - const struct volume_key *vk, - digests_t digests); + const struct volume_key *vk); void LUKS2_digests_erase_unused(struct crypt_device *cd, struct luks2_hdr *hdr); @@ -249,18 +245,6 @@ int LUKS2_digest_verify(struct crypt_device *cd, int LUKS2_digest_dump(struct crypt_device *cd, int digest); -int LUKS2_digest_json_set(struct crypt_device *cd, - struct luks2_hdr *hdr, - int digest, - const char *json); - -int LUKS2_digests_assign(struct crypt_device *cd, - struct luks2_hdr *hdr, - int keyslot, - digests_t digests, - int assign, - int commit); - int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr, int keyslot, @@ -275,10 +259,9 @@ int LUKS2_digest_segment_assign(struct crypt_device *cd, int assign, int commit); -int LUKS2_digests_by_keyslot(struct crypt_device *cd, +int LUKS2_digest_by_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr, - int keyslot, - digests_t digests); + int keyslot); int LUKS2_digest_create(struct crypt_device *cd, const char *type, diff --git a/lib/luks2/luks2_digest.c b/lib/luks2/luks2_digest.c index 5e628339..aa7c06fc 100644 --- a/lib/luks2/luks2_digest.c +++ b/lib/luks2/luks2_digest.c @@ -28,22 +28,6 @@ static const digest_handler *digest_handlers[LUKS2_DIGEST_MAX] = { NULL }; -int crypt_digest_register(const digest_handler *handler) -{ - int i; - - for (i = 0; i < LUKS2_DIGEST_MAX && digest_handlers[i]; i++) { - if (!strcmp(digest_handlers[i]->name, handler->name)) - return -EINVAL; - } - - if (i == LUKS2_DIGEST_MAX) - return -EINVAL; - - digest_handlers[i] = handler; - return 0; -} - const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type) { int i; @@ -107,13 +91,11 @@ int LUKS2_digest_create(struct crypt_device *cd, return dh->store(cd, digest, vk->key, vk->keylength) ?: digest; } -int LUKS2_digests_by_keyslot(struct crypt_device *cd, +int LUKS2_digest_by_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr, - int keyslot, - digests_t digests) + int keyslot) { char keyslot_name[16]; - int i = 0; json_object *jobj_digests, *jobj_digest_keyslots; if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1) @@ -124,13 +106,10 @@ int LUKS2_digests_by_keyslot(struct crypt_device *cd, json_object_object_foreach(jobj_digests, key, val) { json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots); if (LUKS2_array_jobj(jobj_digest_keyslots, keyslot_name)) - digests[i++] = atoi(key); + return atoi(key); } - if (i < LUKS2_DIGEST_MAX) - digests[i] = -1; - - return i ? 0 : -ENOENT; + return -ENOENT; } int LUKS2_digest_verify(struct crypt_device *cd, @@ -139,28 +118,23 @@ int LUKS2_digest_verify(struct crypt_device *cd, int keyslot) { const digest_handler *h; - digests_t digests; - int i, r; + int digest, r; - r = LUKS2_digests_by_keyslot(cd, hdr, keyslot, digests); - if (r == -ENOENT) + digest = LUKS2_digest_by_keyslot(cd, hdr, keyslot); + if (digest == -ENOENT) return 0; - if (r < 0) + if (digest < 0) + return digest; + + log_dbg("Verifying key from keyslot %d, digest %d.", keyslot, digest); + h = LUKS2_digest_handler(cd, digest); + if (!h) + return -EINVAL; + + r = h->verify(cd, digest, vk->key, vk->keylength); + if (r < 0) { + log_dbg("Digest %d (%s) verify failed with %d.", digest, h->name, r); return r; - - for (i = 0; i < LUKS2_DIGEST_MAX && digests[i] != -1 ; i++) { - log_dbg("Verifying key from keyslot %d, digest %d.", - keyslot, digests[i]); - h = LUKS2_digest_handler(cd, digests[i]); - if (!h) - return -EINVAL; - - r = h->verify(cd, digests[i], vk->key, vk->keylength); - if (r < 0) { - log_dbg("Digest %d (%s) verify failed with %d.", - digests[i], h->name, r); - return r; - } } return 0; @@ -176,49 +150,39 @@ int LUKS2_digest_dump(struct crypt_device *cd, int digest) return h->dump(cd, digest); } -int LUKS2_digests_verify_by_segment(struct crypt_device *cd, +int LUKS2_digest_verify_by_segment(struct crypt_device *cd, struct luks2_hdr *hdr, int segment, - const struct volume_key *vk, - digests_t digests) + const struct volume_key *vk) { const digest_handler *h; - digests_t tmp; - int *digest, r, i = 0; + int digest, r; - digest = digests ? digests : tmp; + digest = LUKS2_digest_by_segment(cd, hdr, segment); + if (digest < 0) + return digest; - r = LUKS2_digests_by_segment(cd, hdr, segment, digest); - if (r) + log_dbg("Verifying key digest %d.", digest); + + h = LUKS2_digest_handler(cd, digest); + if (!h) + return -EINVAL; + + r = h->verify(cd, digest, vk->key, vk->keylength); + if (r < 0) { + log_dbg("Digest %d (%s) verify failed with %d.", digest, h->name, r); return r; - - while (i < LUKS2_DIGEST_MAX && digest[i] != -1) { - log_dbg("Verifying key digest %d.", digest[i]); - - h = LUKS2_digest_handler(cd, digest[i]); - if (!h) - return -EINVAL; - - r = h->verify(cd, digest[i], vk->key, vk->keylength); - if (r < 0) { - log_dbg("Digest %d (%s) verify failed with %d.", digest[i], h->name, r); - return r; - } - - i++; } return 0; } -int LUKS2_digests_by_segment(struct crypt_device *cd, +int LUKS2_digest_by_segment(struct crypt_device *cd, struct luks2_hdr *hdr, - int segment, - digests_t digests) + int segment) { char segment_name[16]; json_object *jobj_digests, *jobj_digest_segments; - int i = 0; json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); @@ -230,13 +194,10 @@ int LUKS2_digests_by_segment(struct crypt_device *cd, if (!LUKS2_array_jobj(jobj_digest_segments, segment_name)) continue; - digests[i++] = atoi(key); + return atoi(key); } - if (i < LUKS2_DIGEST_MAX) - digests[i] = -1; - - return i ? 0 : -ENOENT; + return -ENOENT; } static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr, @@ -269,20 +230,6 @@ static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr, return 0; } -int LUKS2_digests_assign(struct crypt_device *cd, struct luks2_hdr *hdr, - int keyslot, digests_t digests, int assign, int commit) -{ - int i, r; - - for (i = 0; i < LUKS2_DIGEST_MAX && digests[i] != -1; i++) { - r = LUKS2_digest_assign(cd, hdr, keyslot, digests[i], assign, 0); - if (r < 0) - return r; - } - - return commit ? LUKS2_hdr_write(cd, hdr) : 0; -} - int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr, int keyslot, int digest, int assign, int commit) { diff --git a/lib/luks2/luks2_internal.h b/lib/luks2/luks2_internal.h index a3fea473..6a83d77a 100644 --- a/lib/luks2/luks2_internal.h +++ b/lib/luks2/luks2_internal.h @@ -124,12 +124,9 @@ typedef struct { digest_dump_func dump; } digest_handler; -int crypt_digest_register(const digest_handler *handler); const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type); #define CRYPT_ANY_DIGEST -1 -int crypt_keyslot_assign_digest(struct crypt_device *cd, int keyslot, int digest); -int crypt_keyslot_unassign_digest(struct crypt_device *cd, int keyslot, int digest); /** * LUKS2 token handlers (internal use only) diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c index ed207049..20c0eec1 100644 --- a/lib/luks2/luks2_keyslot.c +++ b/lib/luks2/luks2_keyslot.c @@ -82,75 +82,23 @@ int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr, const char *type) return -EINVAL; } -static int digests_by_segment(json_object *jobj_digests, const char *segment, - digests_t digests) -{ - json_object *jobj_segs; - int i = 0; - - json_object_object_foreach(jobj_digests, dig, val) { - json_object_object_get_ex(val, "segments", &jobj_segs); - if (LUKS2_array_jobj(jobj_segs, segment)) - digests[i++] = atoi(dig); - } - - if (i < LUKS2_DIGEST_MAX) - digests[i] = -1; - - return i ? 0 : -ENOENT; -} - -static int is_in(const int super[], int super_size, int elem) -{ - int i; - - for (i = 0; i < super_size && super[i] != -1; i++) - if (super[i] == elem) - return 1; - return 0; -} - -static int is_subset(const int super[], const int sub[], int super_size) -{ - int i; - - for (i = 0; i < super_size && sub[i] != -1; i++) - if (!is_in(super, super_size, sub[i])) - return 0; - - return 1; -} - int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment) { - char keyslot_name[16], segment_name[16]; - digests_t keyslot_digests, segment_digests; - json_object *jobj_digests; - int r = -ENOENT; + int keyslot_digest, segment_digest; /* no need to check anything */ if (segment == CRYPT_ANY_SEGMENT) return 0; - if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1 || - snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1) + keyslot_digest = LUKS2_digest_by_keyslot(NULL, hdr, keyslot); + if (keyslot_digest < 0) return -EINVAL; - /* empty set is subset of any set and it'd be wrong */ - json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); - r = LUKS2_digests_by_keyslot(NULL, hdr, keyslot, keyslot_digests); - if (r) - return r; + segment_digest = LUKS2_digest_by_segment(NULL, hdr, segment); + if (segment_digest < 0) + return -EINVAL; - /* empty set can't be superset of non-empty one */ - if (digests_by_segment(jobj_digests, segment_name, segment_digests)) - return r; - - /* - * keyslot may activate segment if set of digests for keyslot - * is actually subset of set of digests for segment - */ - return is_subset(segment_digests, keyslot_digests, LUKS2_DIGEST_MAX) ? 0 : -ENOENT; + return segment_digest == keyslot_digest ? 0 : -ENOENT; } int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment) @@ -160,7 +108,6 @@ int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment) json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); - /* keyslot digests must be subset of segment digests */ json_object_object_foreach(jobj_keyslots, slot, val) { UNUSED(val); if (!LUKS2_keyslot_for_segment(hdr, atoi(slot), segment)) diff --git a/lib/setup.c b/lib/setup.c index b8ba64ae..1a8f3f8d 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -2017,30 +2017,27 @@ int crypt_repair(struct crypt_device *cd, return r; } -static const char *crypt_get_key_description_by_digests(struct crypt_device *cd, digests_t digests) +static const char *crypt_get_key_description_by_digest(struct crypt_device *cd, int digest) { - char *desc, digests_str[17]; - int i = 0, r; - size_t len, off = 0; + char *desc, digest_str[3]; + int r; + size_t len; if (!crypt_get_uuid(cd)) return NULL; - while (i < LUKS2_DIGEST_MAX && digests[i] != -1) { - r = snprintf(digests_str + off, sizeof(digests_str) - off, "d%u", digests[i++]); - if (r < 0 || (size_t)r >= sizeof(digests_str) - off) - return NULL; - off += (size_t) r; - } + r = snprintf(digest_str, sizeof(digest_str), "d%u", digest); + if (r < 0 || (size_t)r >= sizeof(digest_str)) + return NULL; - /* "cryptsetup:-" + \0 */ - len = strlen(crypt_get_uuid(cd)) + strlen(digests_str) + 13; + /* "cryptsetup:-" + \0 */ + len = strlen(crypt_get_uuid(cd)) + strlen(digest_str) + 13; desc = malloc(len); if (!desc) return NULL; - r = snprintf(desc, len, "%s:%s-%s", "cryptsetup", crypt_get_uuid(cd), digests_str); + r = snprintf(desc, len, "%s:%s-%s", "cryptsetup", crypt_get_uuid(cd), digest_str); if (r < 0 || (size_t)r >= len) { free(desc); return NULL; @@ -2051,23 +2048,13 @@ static const char *crypt_get_key_description_by_digests(struct crypt_device *cd, static const char *crypt_get_key_description_by_segment(struct crypt_device *cd, int segment) { - digests_t digests; - - if (LUKS2_digests_by_segment(cd, &cd->u.luks2.hdr, segment, digests)) - return NULL; - - return crypt_get_key_description_by_digests(cd, digests); + return crypt_get_key_description_by_digest(cd, LUKS2_digest_by_segment(cd, &cd->u.luks2.hdr, segment)); } /* curently internal only (candidate for new API call) */ const char *crypt_get_key_description_by_keyslot(struct crypt_device *cd, int keyslot) { - digests_t digests; - - if (LUKS2_digests_by_keyslot(cd, &cd->u.luks2.hdr, keyslot, digests)) - return NULL; - - return crypt_get_key_description_by_digests(cd, digests); + return crypt_get_key_description_by_digest(cd, LUKS2_digest_by_keyslot(cd, &cd->u.luks2.hdr, keyslot)); } int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size) @@ -2558,8 +2545,7 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, const char *new_passphrase, size_t new_passphrase_size) { - digests_t digests; - int r, active_slots; + int digest, r, active_slots; struct volume_key *vk = NULL; log_dbg("Adding new keyslot, existing passphrase %sprovided," @@ -2608,10 +2594,11 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, r = LUKS_set_key(keyslot, CONST_CAST(char*)new_passphrase, new_passphrase_size, &cd->u.luks1.hdr, vk, cd); else { - r = LUKS2_digests_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk, digests); + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + digest = r; if (r >= 0) - r = LUKS2_digests_assign(cd, &cd->u.luks2.hdr, keyslot, digests, 1, 0); + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); if (r >= 0) r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot, @@ -2640,8 +2627,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, const char *new_passphrase, size_t new_passphrase_size) { - digests_t digests; - int r; + int digest, r; struct volume_key *vk = NULL; if (!passphrase || !new_passphrase) @@ -2659,8 +2645,11 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, else if (isLUKS2(cd->type)) { r = LUKS2_keyslot_open(cd, keyslot_old, CRYPT_ANY_SEGMENT, passphrase, passphrase_size, &vk); /* will fail for keyslots w/o digest. fix if supported in a future */ - if (r >= 0 && LUKS2_digests_by_keyslot(cd, &cd->u.luks2.hdr, r, digests)) - r = -EINVAL; + if (r >= 0) { + digest = LUKS2_digest_by_keyslot(cd, &cd->u.luks2.hdr, r); + if (digest < 0) + r = -EINVAL; + } } else r = -EINVAL; if (r < 0) @@ -2691,7 +2680,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, &cd->u.luks1.hdr, vk, cd); } else if (isLUKS2(cd->type)) { if (keyslot_old != keyslot_new) { - r = LUKS2_digests_assign(cd, &cd->u.luks2.hdr, keyslot_new, digests, 1, 0); + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, digest, 1, 0); if (r < 0) goto out; } else { @@ -2740,8 +2729,7 @@ int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, size_t new_keyfile_size, size_t new_keyfile_offset) { - digests_t digests; - int r, active_slots; + int digest, r, active_slots; size_t passwordLen, new_passwordLen; char *password = NULL, *new_password = NULL; struct volume_key *vk = NULL; @@ -2799,10 +2787,11 @@ int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, r = LUKS_set_key(keyslot, new_password, new_passwordLen, &cd->u.luks1.hdr, vk, cd); else { - r = LUKS2_digests_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk, digests); + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + digest = r; if (r >= 0) - r = LUKS2_digests_assign(cd, &cd->u.luks2.hdr, keyslot, digests, 1, 0); + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); if (r >= 0) r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot, @@ -3228,7 +3217,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd, if (!vk) return -ENOMEM; - r = LUKS2_digests_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk, NULL); + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); if (r == -EPERM || r == -ENOENT) log_err(cd, _("Volume key does not match the volume.\n")); @@ -3466,14 +3455,14 @@ int crypt_volume_key_verify(struct crypt_device *cd, if (isLUKS1(cd->type)) r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); else if (isLUKS2(cd->type)) - r = LUKS2_digests_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk, NULL); + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); if (r == -EPERM) log_err(cd, _("Volume key does not match the volume.\n")); crypt_free_volume_key(vk); - return r; + return r >= 0 ? 0 : r; } /* @@ -4308,8 +4297,7 @@ int crypt_keyslot_add_by_key(struct crypt_device *cd, size_t passphrase_size, uint32_t flags) { - int r; - digests_t digests = { -1, -1 }; + int digest, r; struct volume_key *vk = NULL; if (!passphrase) @@ -4337,18 +4325,20 @@ int crypt_keyslot_add_by_key(struct crypt_device *cd, /* no segment means we're going to store key without assigned segment (unused in dm-crypt) */ if (flags & CRYPT_VOLUME_KEY_NO_SEGMENT) - r = digests[0] = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk); + digest = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk); else - r = LUKS2_digests_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk, digests); + digest = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + + r = digest; if (r < 0) { log_err(cd, _("Volume key does not match the volume.\n")); goto out; } - r = LUKS2_digests_assign(cd, &cd->u.luks2.hdr, keyslot, digests, 1, 0); + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); if (r < 0) { - log_err(cd, _("Failed to assign keyslot %d to digests.\n"), keyslot); + log_err(cd, _("Failed to assign keyslot %d to digest.\n"), keyslot); goto out; }