From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1kAqXX-0007Ul-5E for mharc-grub-devel@gnu.org; Wed, 26 Aug 2020 04:12:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32922) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kAqXS-0007Sy-0U for grub-devel@gnu.org; Wed, 26 Aug 2020 04:12:10 -0400 Received: from wout1-smtp.messagingengine.com ([64.147.123.24]:58523) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kAqXP-0005Qm-Mr for grub-devel@gnu.org; Wed, 26 Aug 2020 04:12:09 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id 5128A10AE; Wed, 26 Aug 2020 04:12:06 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Wed, 26 Aug 2020 04:12:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm1; bh=7KISmgRTWRkUjLCfkGGmm0CC6jH 71q2rDrnLTQ1BoiU=; b=LW7NQ//j6xKp0mTazSmxbvql3jcIjaegfhYW+eHptcS zm/kb7IZjzBTY/4QGoCBDbLdEvQgcDxWc581SedF+3/4R2XEzj+uV1oBw0pn/ngq NslHQJjG4MHBOqLw6Z/hTS8EvWzUhchWuiXRPBoL5RLhnYneBDFdFfxgvmPcHbdL c7Rm1iIs7ZWqRmH/WBJ86U5ajtVmDIQhoyp4pR9TMJ6DnHRhkPPVicjp5ez8b0UD rf3+iwDZEnZNVJVh6NwlO2J4hLNt1k/AGYrdGFRLOi7vFgjE/rHbhEaZnfeANYij ILasVCN/Puaw2BiLrrQZe2ssR3rRNN8DgEj36I3CUKw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=7KISmg RTWRkUjLCfkGGmm0CC6jH71q2rDrnLTQ1BoiU=; b=S1UqnTBoPkRLhsGIVf0UZ5 tqN5jWgPEqPwPuvW0ljU9t4cCMfNZSoHaA4DF8eL2Hg6F8GkSdB/h6TXbEXcWNXo M9/1ugrGV/0X1qH7KBkG7M8MB6u1zCeZzhfPxI6fDgOF/wdLSXPkvutoImCfoGkV GaXehGOwsKaQwFAthj9IrXMfsDaL2Fz9tfRVs88W7xhVOEA+ZvybcjHTKuKvP0p9 GCbl/9rPmpHk+cO61rr8o2WSVjOLm4rHE0xCP9EtjxAYMHwgrxtwxT3q3fQe+mgp Poj+gmLH3lM6M/OpIlgEVD8U5aIQ8GU7O6eb1Tbk88jW8uUvXE9gQ/MPXrHJNk3Q == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduiedruddvvddgtdduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepkeelrdduvddrfeekrddvfeeinecuvehluhhsthgvrhfuihiivgepleenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (x590c26ec.dyn.telefonica.de [89.12.38.236]) by mail.messagingengine.com (Postfix) with ESMTPA id 37EC23280063; Wed, 26 Aug 2020 04:12:05 -0400 (EDT) Received: from localhost (xps [10.192.0.12]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 667526a1 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 26 Aug 2020 08:12:04 +0000 (UTC) Date: Wed, 26 Aug 2020 10:14:02 +0200 From: Patrick Steinhardt To: grub-devel@gnu.org Cc: Denis GNUtoo Carikli , Glenn Washburn , Daniel Kiper Subject: [PATCH v2 9/9] cryptodisk: Properly handle non-512 byte sized sectors Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="CE+1k2dSO48ffgeK" Content-Disposition: inline In-Reply-To: Received-SPF: pass client-ip=64.147.123.24; envelope-from=ps@pks.im; helo=wout1-smtp.messagingengine.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/26 03:16:08 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Aug 2020 08:12:10 -0000 --CE+1k2dSO48ffgeK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable =46rom: Glenn Washburn By default, dm-crypt internally uses an IV that corresponds to 512-byte sectors, even when a larger sector size is specified. What this means is that when using a larger sector size, the IV is incremented every sector. However, the amount the IV is incremented is the number of 512 byte blocks in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to the number of, for example, 4K sectors. So each cipher block in the fifth 4K sector will be encrypted with an IV equal to 32, as opposed to 32-39 for each sequential 512 byte block or an IV of 4 for each cipher block in the sector. There are some encryption utilities which do it the intuitive way and have the IV equal to the sector number regardless of sector size (ie. the fifth sector would have an IV of 4 for each cipher block). And this is supported by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3 with the --iv-large-sectors, though not with LUKS headers (only with --type plain). However, support for this has not been included as grub does not support plain devices right now. One gotcha here is that the encrypted split keys are encrypted with a hard- coded 512-byte sector size. So even if your data is encrypted with 4K sector sizes, the split key encrypted area must be decrypted with a block size of 512 (ie the IV increments every 512 bytes). This made these changes less aestetically pleasing than desired. Signed-off-by: Glenn Washburn Reviewed-by: Patrick Steinhardt --- grub-core/disk/cryptodisk.c | 47 +++++++++++++++++++++---------------- grub-core/disk/luks.c | 5 ++-- grub-core/disk/luks2.c | 6 ++++- include/grub/cryptodisk.h | 2 +- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 0b63b7d96..0b8ac5b30 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -33,6 +33,9 @@ =20 GRUB_MOD_LICENSE ("GPLv3+"); =20 +/* Internally encrypted sectors are 512 bytes regardless of what the crypt= odisk is */ +#define CRYPT_LOG_SECTOR_SIZE 9 + grub_cryptodisk_dev_t grub_cryptodisk_list; =20 static const struct grub_arg_option options[] =3D @@ -224,7 +227,8 @@ lrw_xor (const struct lrw_sector *sec, static gcry_err_code_t grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector, int do_encrypt) + grub_disk_addr_t sector, grub_size_t sector_size, + int do_encrypt) { grub_size_t i; gcry_err_code_t err; @@ -237,12 +241,13 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data,= len) : grub_crypto_ecb_decrypt (dev->cipher, data, data, len)); =20 - for (i =3D 0; i < len; i +=3D (1U << dev->log_sector_size)) + for (i =3D 0; i < len; i +=3D (1U << sector_size)) { grub_size_t sz =3D ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)); grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]; + grub_uint64_t iv_calc; =20 if (dev->rekey) { @@ -270,7 +275,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, if (!ctx) return GPG_ERR_OUT_OF_MEMORY; =20 - tmp =3D grub_cpu_to_le64 (sector << dev->log_sector_size); + tmp =3D grub_cpu_to_le64 (sector << sector_size); dev->iv_hash->init (ctx); dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp)); @@ -281,14 +286,16 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, } break; case GRUB_CRYPTODISK_MODE_IV_PLAIN64: - iv[1] =3D grub_cpu_to_le32 (sector >> 32); + iv_calc =3D sector << (sector_size - CRYPT_LOG_SECTOR_SIZE); + iv[1] =3D grub_cpu_to_le32 (iv_calc >> 32); /* FALLTHROUGH */ case GRUB_CRYPTODISK_MODE_IV_PLAIN: - iv[0] =3D grub_cpu_to_le32 (sector & 0xFFFFFFFF); + iv_calc =3D sector << (sector_size - CRYPT_LOG_SECTOR_SIZE); + iv[0] =3D grub_cpu_to_le32 (iv_calc & 0xFFFFFFFF); break; case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64: - iv[1] =3D grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size)); - iv[0] =3D grub_cpu_to_le32 ((sector << dev->log_sector_size) + iv[1] =3D grub_cpu_to_le32 (sector >> (32 - sector_size)); + iv[0] =3D grub_cpu_to_le32 ((sector << sector_size) & 0xFFFFFFFF); break; case GRUB_CRYPTODISK_MODE_IV_BENBI: @@ -311,10 +318,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, case GRUB_CRYPTODISK_MODE_CBC: if (do_encrypt) err =3D grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + (1U << sector_size), iv); else err =3D grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + (1U << sector_size), iv); if (err) return err; break; @@ -322,10 +329,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, case GRUB_CRYPTODISK_MODE_PCBC: if (do_encrypt) err =3D grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + (1U << sector_size), iv); else err =3D grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + (1U << sector_size), iv); if (err) return err; break; @@ -337,7 +344,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, if (err) return err; =20 - for (j =3D 0; j < (1U << dev->log_sector_size); + for (j =3D 0; j < (1U << sector_size); j +=3D dev->cipher->cipher->blocksize) { grub_crypto_xor (data + i + j, data + i + j, iv, @@ -368,11 +375,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, if (do_encrypt) err =3D grub_crypto_ecb_encrypt (dev->cipher, data + i,=20 data + i, - (1U << dev->log_sector_size)); + (1U << sector_size)); else err =3D grub_crypto_ecb_decrypt (dev->cipher, data + i,=20 data + i, - (1U << dev->log_sector_size)); + (1U << sector_size)); if (err) return err; lrw_xor (&sec, dev, data + i); @@ -381,10 +388,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *de= v, case GRUB_CRYPTODISK_MODE_ECB: if (do_encrypt) err =3D grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + (1U << sector_size)); else err =3D grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + (1U << sector_size)); if (err) return err; break; @@ -399,9 +406,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, gcry_err_code_t grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector) + grub_disk_addr_t sector, grub_size_t sector_size) { - return grub_cryptodisk_endecrypt (dev, data, len, sector, 0); + return grub_cryptodisk_endecrypt (dev, data, len, sector, sector_size, 0= ); } =20 grub_err_t @@ -766,7 +773,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_= t sector, } gcry_err =3D grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf, size << disk->log_sector_size, - sector, 0); + sector, dev->log_sector_size, 0); return grub_crypto_gcry_error (gcry_err); } =20 @@ -807,7 +814,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr= _t sector, =20 gcry_err =3D grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp, size << disk->log_sector_size, - sector, 1); + sector, disk->log_sector_size, 1); if (gcry_err) { grub_free (tmp); diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 59702067a..b30c4551e 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -30,6 +30,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); =20 #define MAX_PASSPHRASE 256 +#define LOG_SECTOR_SIZE 9 =20 #define LUKS_KEY_ENABLED 0x00AC71F3 =20 @@ -124,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_= uuid, return NULL; newdev->offset =3D grub_be_to_cpu32 (header.payloadOffset); newdev->source_disk =3D NULL; - newdev->log_sector_size =3D 9; + newdev->log_sector_size =3D LOG_SECTOR_SIZE; newdev->total_length =3D grub_disk_get_size (disk) - newdev->offset; grub_memcpy (newdev->uuid, uuid, sizeof (uuid)); newdev->modname =3D "luks"; @@ -247,7 +248,7 @@ luks_recover_key (grub_disk_t source, return err; } =20 - gcry_err =3D grub_cryptodisk_decrypt (dev, split_key, length, 0); + gcry_err =3D grub_cryptodisk_decrypt (dev, split_key, length, 0, LOG= _SECTOR_SIZE); if (gcry_err) { grub_free (split_key); diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c index 26e1126b1..1f5f9766a 100644 --- a/grub-core/disk/luks2.c +++ b/grub-core/disk/luks2.c @@ -492,7 +492,11 @@ luks2_decrypt_key (grub_uint8_t *out_key, goto err; } =20 - gcry_ret =3D grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0); + /* + * The encrypted key slots are always with 512byte sectors, + * regardless of encrypted data sector size + */ + gcry_ret =3D grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,= 9); if (gcry_ret) { ret =3D grub_crypto_gcry_error (gcry_ret); diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index e1b21e785..06653a622 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -139,7 +139,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, gcry_err_code_t grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector); + grub_disk_addr_t sector, grub_size_t sector_size); grub_err_t grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name, grub_disk_t source); --=20 2.28.0 --CE+1k2dSO48ffgeK Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAl9GGckACgkQVbJhu7ck PpQm5w/8DcUHaWA+IOVyPiZNATI9b2f+ewXvdAKT4NtJMfEoFxDkobYp5Ed5uY7i 4JkiUgri7uEoqcfsUWq52rK9aV0nAd81mmehAvLaJ2daTkVY99QjPKim6JeNKad3 V6wd0j8TQ/OZP9dQBj4HXkbuEXKFuBNsaOot7SoJ08COuCX/Vsr/KhQzEpHuZh1p nnJPtVx4wplOJIL85o/BYay6GVG8mgL8pRo84y/SJ1GshpmTDuMzGYafjru1+6IR YWXHHUlkUQoAQhiuWlU+kZo8L+w0y6o6hPpmLl/VHz2Xdd0l1uvwIbjiiCzkm8pv Be9XMJ0y1LhasxLcPqU6uaAw9W/FkjPgy/UGQ7NDcMy69UAmmifhCZqhcJqG2QGE Kp9XrX9Z/saH1k03MjRKAWhQe/PUjADL+nOmYpY+r9A0dyMk/HYXjmVBkwWCSb2q CrHCrSa8kNl+Wm+D1JF6T5vsurYZYvN3MdATxoy1WJFmu+i9u74DBrG2b4K3bv5H quVh8GdZTQb6Ny6UW7W5OGBnPY9LPgSJ2D7YCqqEWYNcHgDhDCYfNyvslllN7yeW zKaWpl77iXrweUhKAoWx3aiheVKGgxB6yaZsDFa9t4ledVsNf768pLcWEGh0JtOS svqKFQxtUoT8JRRvM2MmS78Tlkp4KfA749abXPdxQ/uMCd7R4mc= =MdTD -----END PGP SIGNATURE----- --CE+1k2dSO48ffgeK--