Update unlock_luks2() and related functions to accept a binary passphrase instead of a string passphrase. This will allow unlocking using hashed data. For now this is internal to the luks implementation. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- drivers/block/luks.c | 3 ++- drivers/block/luks2.c | 41 ++++++++++++++++++++--------------- drivers/block/luks_internal.h | 4 +++- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/block/luks.c b/drivers/block/luks.c index 6a1e6f9a3ca..93b50dd105a 100644 --- a/drivers/block/luks.c +++ b/drivers/block/luks.c @@ -452,7 +452,8 @@ int luks_unlock(struct udevice *blk, struct disk_partition *pinfo, version = be16_to_cpu(*(__be16 *)(buffer + LUKS_MAGIC_LEN)); if (version == LUKS_VERSION_2) - return unlock_luks2(blk, pinfo, pass, master_key, key_size); + return unlock_luks2(blk, pinfo, (const u8 *)pass, strlen(pass), + master_key, key_size); if (version != LUKS_VERSION_1) { log_debug("unsupported LUKS version %d\n", version); diff --git a/drivers/block/luks2.c b/drivers/block/luks2.c index 6836c372de2..57e6b9f37d9 100644 --- a/drivers/block/luks2.c +++ b/drivers/block/luks2.c @@ -586,8 +586,9 @@ static int decrypt_km_cbc(u8 *derived_key, uint key_size, const char *encrypt, * Return: 0 on success, negative error code on failure */ static int try_keyslot_pbkdf2(struct udevice *blk, struct disk_partition *pinfo, - const struct luks2_keyslot *ks, const char *pass, - mbedtls_md_type_t md_type, u8 *cand_key) + const struct luks2_keyslot *ks, const u8 *pass, + size_t pass_len, mbedtls_md_type_t md_type, + u8 *cand_key) { struct blk_desc *desc = dev_get_uclass_plat(blk); int ret, km_blocks, size; @@ -597,10 +598,10 @@ static int try_keyslot_pbkdf2(struct udevice *blk, struct disk_partition *pinfo, log_debug("LUKS2: trying keyslot with %u iters\n", ks->kdf.iters); /* Derive key from passphrase */ - ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, (const u8 *)pass, - strlen(pass), ks->kdf.salt, - ks->kdf.salt_len, ks->kdf.iters, - ks->area.key_size, derived_key); + ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pass, pass_len, + ks->kdf.salt, ks->kdf.salt_len, + ks->kdf.iters, ks->area.key_size, + derived_key); if (ret) return -EPROTO; @@ -655,8 +656,8 @@ out: /* Unlock using Argon2 keyslot */ static int try_keyslot_argon2(struct udevice *blk, struct disk_partition *pinfo, - const struct luks2_keyslot *ks, const char *pass, - u8 *cand_key) + const struct luks2_keyslot *ks, const u8 *pass, + size_t pass_len, u8 *cand_key) { struct blk_desc *desc = dev_get_uclass_plat(blk); int ret, km_blocks, size; @@ -667,11 +668,11 @@ static int try_keyslot_argon2(struct udevice *blk, struct disk_partition *pinfo, ks->kdf.time, ks->kdf.memory, ks->kdf.cpus); /* Derive key from passphrase using Argon2id */ - log_debug("LUKS2 Argon2: passphrase='%s', t=%u, m=%u, p=%u, saltlen=%d, keylen=%u\n", - pass, ks->kdf.time, ks->kdf.memory, ks->kdf.cpus, + log_debug("LUKS2 Argon2: pass_len=%zu, t=%u, m=%u, p=%u, saltlen=%d, keylen=%u\n", + pass_len, ks->kdf.time, ks->kdf.memory, ks->kdf.cpus, ks->kdf.salt_len, ks->area.key_size); ret = argon2id_hash_raw(ks->kdf.time, ks->kdf.memory, ks->kdf.cpus, - pass, strlen(pass), ks->kdf.salt, + pass, pass_len, ks->kdf.salt, ks->kdf.salt_len, derived_key, ks->area.key_size); if (ret) { @@ -826,8 +827,9 @@ static int verify_master_key(const struct luks2_digest *digest, static int try_unlock_keyslot(struct udevice *blk, struct disk_partition *pinfo, ofnode keyslot_node, const struct luks2_digest *digest, - mbedtls_md_type_t md_type, const char *pass, - u8 *master_key, uint *key_sizep) + mbedtls_md_type_t md_type, const u8 *pass, + size_t pass_len, u8 *master_key, + uint *key_sizep) { struct luks2_keyslot keyslot; u8 cand_key[128]; @@ -846,12 +848,13 @@ static int try_unlock_keyslot(struct udevice *blk, struct disk_partition *pinfo, /* Try the keyslot using the appropriate KDF */ if (keyslot.kdf.type == LUKS2_KDF_PBKDF2) { log_debug("LUKS2: calling try_keyslot_pbkdf2\n"); - ret = try_keyslot_pbkdf2(blk, pinfo, &keyslot, pass, md_type, - cand_key); + ret = try_keyslot_pbkdf2(blk, pinfo, &keyslot, pass, pass_len, + md_type, cand_key); } else { /* Argon2 (already checked for CONFIG_ARGON2 support) */ log_debug("LUKS2: calling try_keyslot_argon2\n"); - ret = try_keyslot_argon2(blk, pinfo, &keyslot, pass, cand_key); + ret = try_keyslot_argon2(blk, pinfo, &keyslot, pass, pass_len, + cand_key); } log_debug("LUKS2: keyslot try returned %d\n", ret); @@ -874,7 +877,8 @@ static int try_unlock_keyslot(struct udevice *blk, struct disk_partition *pinfo, } int unlock_luks2(struct udevice *blk, struct disk_partition *pinfo, - const char *pass, u8 *master_key, uint *key_sizep) + const u8 *pass, size_t pass_len, u8 *master_key, + uint *key_sizep) { ofnode keyslots_node, keyslot_node; struct luks2_digest digest; @@ -892,7 +896,8 @@ int unlock_luks2(struct udevice *blk, struct disk_partition *pinfo, ret = -EACCES; ofnode_for_each_subnode(keyslot_node, keyslots_node) { ret = try_unlock_keyslot(blk, pinfo, keyslot_node, &digest, - md_type, pass, master_key, key_sizep); + md_type, pass, pass_len, master_key, + key_sizep); if (!ret) /* Successfully unlocked! */ break; diff --git a/drivers/block/luks_internal.h b/drivers/block/luks_internal.h index 3bc572cdfd9..6b0e41267ff 100644 --- a/drivers/block/luks_internal.h +++ b/drivers/block/luks_internal.h @@ -51,11 +51,13 @@ void essiv_decrypt(const u8 *derived_key, uint key_size, u8 *expkey, u8 *km, * @blk: Block device * @pinfo: Partition information * @pass: Passphrase to unlock the partition + * @pass_len: Length of the passphrase in bytes * @master_key: Buffer to receive the decrypted master key * @key_sizep: Returns the key size * Return: 0 on success, -ve on error */ int unlock_luks2(struct udevice *blk, struct disk_partition *pinfo, - const char *pass, u8 *master_key, uint *key_sizep); + const u8 *pass, size_t pass_len, u8 *master_key, + uint *key_sizep); #endif /* __LUKS_INTERNAL_H__ */ -- 2.43.0