The legacy method for metadata encryption on adoptable storage failed
when the size of the block device isn't a multiple of the crypto sector size.
Update the size of dm-crypt device according to sector size
before construct dm_target.
Bug: 248582018
Change-Id: I5c78889bdfedca7f7b0704500fc313d7a48d5a3b
Signed-off-by: Hongyu Jin <hongyu.jin@unisoc.com>
Now that emulated FBE is no longer supported, there is no longer any
distinction between native FBE and emulated FBE. There is just FBE.
Referring to FBE as "fscrypt" is also poor practice, as fscrypt (the
Linux kernel support for filesystem-level encryption) is just one part
of FBE, the Android feature.
Therefore, rename fscrypt_is_native() to IsFbeEnabled().
Bug: 232458753
Change-Id: Idf4cb25d37bc3e81836fcc5a1d96f79ccfa443b7
Since Android 10, new devices have been required to use FBE instead of
FDE. Therefore, the FDE code is no longer needed.
Remove most of cryptfs.cpp. A few parts of it need to be kept in order
to support the dm-crypt method of adoptable storage encryption.
Keep the FDE-specific binder methods stubbed out for now until their
callers can be removed.
Bug: 191796797
Change-Id: I90b1e4cacd2f3e5cce77a82a0af744fcc7da9400
Now that vold uses Keystore2 rather than the Keymaster HAL directly, and
also the new version of Keymaster is called "KeyMint" instead, replace
most of the references to Keymaster in vold with Keystore.
(I decided not to include the "2" in most places, as it seemed
unnecessarily precise in most places, and it would be something that
might need to keep being updated. Only Keystore.{cpp,h} really need to
care about the version number.)
I didn't rename many things in cryptfs.cpp, as that file will be going
away soon anyway. I also left "wait_for_keymaster" and "vdc keymaster
earlyBootEnded" as-is for now, as those are referenced outside vold.
Bug: 183669495
Change-Id: I92cd648fae09f8c9769f7cf34dbf6c6e956be4e8
Add more log messages to make it easier to understand failures in
wait_and_unmount().
Bug: 189250652
Change-Id: I621f54f30bb01cd52c4f9a74dba2d46b4d1a8a9d
ensure_subdirectory_unmounted() was ignoring the return value from
umount(), so it wasn't possible to tell whether it succeeded or failed.
Make it log an error message on failure.
Also, there might be cases where ensure_subdirectory_unmounted() fails
initially but would succeed later, e.g. due to files in a subdirectory
mount being open and requiring processes to be killed. To make this
more robust, keep calling ensure_subdirectory_unmounted() before each
attempt of umount("/data").
I'm not sure whether this will actually fix bug 189250652, as it hasn't
been root-caused yet, but this might help.
Bug: 189250652
Change-Id: I979b12d3c6a88fe3335ff548b1f8a5db43683c4f
In wait_and_unmount(), kill the processes with open files after umount()
has been failing for 2 seconds rather than 17 seconds. This avoids a
long boot delay on devices that use FDE.
Detailed explanation:
On FDE devices, vold needs to unmount the tmpfs /data in order to mount
the real, decrypted /data. On first boot, it also needs to unmount the
unencrypted /data in order to encrypt it in-place.
/data can't be unmounted if files are open inside it. In theory, init
is responsible for killing all processes with open files in /data, via
the property trigger "vold.decrypt=trigger_shutdown_framework".
However, years ago, commit 6e8440fd50 ("cryptfs: kill processes with
open files on tmpfs /data") added a fallback where vold kills the
processes itself. Since then, in practice people have increasingly been
relying on this fallback, as services keep being added that use /data
but don't get stopped by trigger_shutdown_framework.
This is slowing down boot, as vold sleeps for 17 seconds before it
actually kills the processes.
The problematic services include services that are now started
explicitly in the post-fs-data trigger rather than implicitly as part of
a class (e.g., tombstoned), as well as services that now need to be
started as part of one of the early-boot classes like core or early_hal
but can still open files in /data later (e.g. keystore2 and credstore).
Another complication is that on default-encrypted devices (devices with
no PIN/pattern/password), trigger_shutdown_framework isn't run at all,
but rather it's expected that the relevant services simply weren't
started yet. This means that we can't fix the problem just by fixing
trigger_shutdown_framework to kill all the needed processes.
Therefore, given that the vold fallback is being relied on in practice,
and FDE won't be supported much longer anyway (so simple fixes are very
much preferable here), let's just change wait_and_unmount() in vold to
use more appropriate timeouts. Instead of waiting for 17 seconds before
killing processes, just wait for 2 seconds. Keep the total timeout of
20 seconds, but spend most of it retrying killing the processes, and
only if the unmount is still failing.
This avoids the long boot delays in practice.
Bug: 187231646
Bug: 186165644
Test: Tested FDE on Cuttlefish, and checked logcat to verify that the
boot delay is gone.
Change-Id: Id06a9615a87988c8336396c49ee914b35f8d585b
Now that isSecure() always returns true, we can remove it and simplify
all the callers (i.e. cryptfs). Refer to the commit description for
Iaebfef082eca0da8a305043fafb6d85e5de14cf8 for why this function always
return true.
Bug: 181910578
Test: Cuttlefish and bramble boot
Change-Id: I185dd8180bd7842b05295263f0b1aa7205329a88
Make vold use keystore2 for all its operations instead of directly using
keymaster. This way, we won't have any clients that bypass keystore2,
and we'll no longer need to reserve a keymaster operation for vold.
Note that we now hardcode "SecurityLevel::TRUSTED_ENVIRONMENT" (TEE)
when talking to Keystore2 since Keystore2 only allows TEE and STRONGBOX.
Keystore2 presents any SOFTWARE implementation as a TEE to callers when
no "real" TEE is present. As far as storage encryption is concerned,
there's no advantage to using a STRONGBOX when a "real" TEE is present,
and a STRONGBOX can't be present if a "real" TEE isn't, so asking
Keystore2 for a TEE is the best we can do in any situation.
The difference in behaviour only really affects the full disk encryption
code in cryptfs.cpp, which used to explicitly check that the keymaster
device is a "real" TEE (as opposed to a SOFTWARE implementation) before
using it (it can no longer do so since Keystore2 doesn't provide a way
to do this).
A little code history digging (7c49ab0a0b in particular) shows that
cryptfs.cpp cared about two things when using a keymaster.
- 1) that the keys generated by the keymaster were "standalone" keys -
i.e. that the keymaster could operate on those keys without
requiring /data or any other service to be available.
- 2) that the keymaster was a non-SOFTWARE implementation so that things
would still work in case a "real" TEE keymaster was ever somehow
added to the device after first boot.
Today, all "real" TEE keymasters always generate "standalone" keys, and
a TEE has been required in Android devices since at least Android N. The
only two exceptions are Goldfish and ARC++, which have SOFTWARE
keymasters, but both those keymasters also generate "standalone" keys.
We're also no longer worried about possibly adding a "real" TEE KM to
either of those devices after first boot. So there's no longer a reason
cryptfs.cpp can't use the SOFTWARE keymaster on those devices.
There's also already an upgrade path in place (see
test_mount_encrypted_fs() in cryptfs.cpp) to upgrade the kdf that's
being used once a TEE keymaster is added to the device. So it's safe for
cryptfs.cpp to ask for a TEE keymaster from Keystore2 and use it
blindly, without checking whether or not it's a "real" TEE, which is why
Keymaster::isSecure() just returns true now. A future patch will remove
that function and simplify its callers.
Bug: 181910578
Test: cuttlefish and bramble boot. Adding, switching between, stopping
and removing users work.
Change-Id: Iaebfef082eca0da8a305043fafb6d85e5de14cf8
Acquiring a wakelock can fail if the suspend service is unavailable.
Explicitly check that wakelock was acquired before performing
operations that require the device to stay on.
Bug: b/179229598
Test: Boot test on Pixel 4 device
Change-Id: If30087223e44098801a31d1bfd239ac22e891abe
Refactor EncryptInplace.cpp to simplify and improve it a lot. This is
everything that didn't fit into prior commits, including:
- Share a lot more code between ext4, f2fs, and full encryption.
- Improve the log messages. Most importantly, don't spam the log with
huge numbers of messages, and don't log errors in expected cases.
Note: generate_f2fs_info() is still too noisy, but that's part of
"system/extras", not vold, so this change doesn't change that.
- When possible, do 32K reads/writes for f2fs and for full encryption,
not just for ext4. This might improve performance.
- Take advantage of C++ functionality.
- Be more careful about edge cases. E.g. if the calculation of the
number of blocks to encrypt was wrong, don't set vold.encrypt_progress
to > 99 until we're actually done.
The net change is over 200 lines removed.
Before-after comparison of log when enabling metadata encryption:
ext4 before:
I vold : Beginning inplace encryption, nr_sec: 16777216
D vold : cryptfs_enable_inplace(/dev/block/dm-8, /dev/block/by-name/userdata, 16777216, 0)
D vold : Opening/dev/block/by-name/userdata
D vold : Opening/dev/block/dm-8
I vold : Encrypting ext4 filesystem in place...
[omitted 6387 log messages]
I vold : Encrypted to sector 822084608
D vold : cryptfs_enable_inplace_ext4 success
I vold : Inplace encryption complete
ext4 after:
D vold : encrypt_inplace(/dev/block/dm-8, /dev/block/by-name/userdata, 16777216, false)
D vold : ext4 filesystem has 64 block groups
I vold : Encrypting ext4 filesystem on /dev/block/by-name/userdata in-place via /dev/block/dm-8
I vold : 50327 blocks (206 MB) of 2097152 blocks are in-use
D vold : Encrypted 10000 of 50327 blocks
D vold : Encrypted 20000 of 50327 blocks
D vold : Encrypted 30000 of 50327 blocks
D vold : Encrypted 40000 of 50327 blocks
D vold : Encrypted 50000 of 50327 blocks
D vold : Encrypted 50327 of 50327 blocks
I vold : Successfully encrypted ext4 filesystem on /dev/block/by-name/userdata
f2fs before:
I vold : Beginning inplace encryption, nr_sec: 16777216
D vold : cryptfs_enable_inplace(/dev/block/dm-8, /dev/block/by-name/userdata, 16777216, 0)
D vold : Opening/dev/block/by-name/userdata
D vold : Opening/dev/block/dm-8
E vold : Reading ext4 extent caused an exception
D vold : cryptfs_enable_inplace_ext4()=-1
[omitted logspam from f2fs_sparseblock]
I vold : Encrypting from block 0
I vold : Encrypted to block 15872
I vold : Encrypting from block 16384
I vold : Encrypted to block 16385
I vold : Encrypting from block 17408
I vold : Encrypted to block 17412
D vold : cryptfs_enable_inplace_f2fs success
I vold : Inplace encryption complete
f2fs after:
D vold : encrypt_inplace(/dev/block/dm-8, /dev/block/by-name/userdata, 16777216, false)
[omitted logspam from f2fs_sparseblock]
I vold : Encrypting f2fs filesystem on /dev/block/by-name/userdata in-place via /dev/block/dm-8
I vold : 15880 blocks (65 MB) of 2097152 blocks are in-use
D vold : Encrypted 10000 of 15880 blocks
D vold : Encrypted 15880 of 15880 blocks
I vold : Successfully encrypted f2fs filesystem on /dev/block/by-name/userdata
Test: Booted Cuttlefish with metadata encryption enabled and with the
userdata filesystem using (1) ext4, (2) f2fs, and (3) f2fs but
with EncryptInplace.cpp patched to not recognize the filesystem
and fall back to the "full" encryption case. Checked that the log
messages were as expected and that /data was mounted.
I've had no luck testing FDE yet; it doesn't work even without
these changes. Suggestions appreciated...
Change-Id: I08fc8465f7962abd698904b5466f3ed080d53953
This logic is no longer necessary, since the code that creates the
crypto_blkdev (create_crypto_blk_dev() in MetadataCrypt.cpp or in
cryptfs.cpp) now waits for the block device to appear before continuing.
It's also worth noting that the retry loop was only present for ext4,
not for f2fs, yet most Android devices are using f2fs these days.
Test: see I08fc8465f7962abd698904b5466f3ed080d53953
Change-Id: I173ca6cc187a810e008990dfa22aede58632db25
cryptfs_enable_internal() forgot to check the return value of
create_crypto_blk_dev(), so it was continuing to
cryptfs_enable_inplace() when creating the dm-crypt device failed, which
doesn't make sense.
Test: see I08fc8465f7962abd698904b5466f3ed080d53953
Change-Id: If9f20069d0f084150aa887a350f7c0c31a6d80f2
Commit 87999173dd ("Don't corrupt ssd when encrypting and power
fails") added a lot of code to handle pausing in-place conversion from
unencrypted => FDE when the battery was low, and resuming it later.
It was eventually decided that this wasn't needed, and commit
7e17e2d226 ("Don't worry about battery levels when encrypting")
removed the checks for low battery.
This made the partial encryption code unused. So remove it.
Note that this was cluttering up the metadata encryption code too, since
EncryptInplace.cpp is now shared by both FDE and metadata encryption.
Bug: 16868177
Test: see I08fc8465f7962abd698904b5466f3ed080d53953
Change-Id: Ibd2eb08a2aa15938097abcb8a67b5a813c4d76c7
FDE device has shut down and restart the framework.
But restart is not triggered due to umount fail.
umount /data fail with "device is busy"
It is because bind mount /data/data to /data/user/0
We need umount /data/user/0 before umount /data
Bug: 148004718
Test: Flash GSI and check boot with FDE and FBE device.
Change-Id: I919f9e31a9d2d745b297a7ab99b399aa9b293b39
No need for KeyUtil to know how to make a KeyGeneration, it's cleaner
if each module handles it separately. Also, create a CryptoOptions
structure to track metadata encryption options, and simplify legacy
cipher/option handling.
Test: Treehugger
Bug: 147814592
Change-Id: I740063882914097329ff72348d0c0855c26c7aab
More consistency between MetadataCrypt and cryptfs, and steps towards
supporting Adiantum properly in MetadataCrypt.
Test: create private volume on Cuttlefish
Bug: 147814592
Change-Id: Ic3993c1fde11b4f5a9e6cc8ee588a7d92241c6ab
For some reason this can be racy; until we understand the root cause,
retry to unblock presubmit.
Bug: 149396179
Test: atest AdoptableHostTest no longer hangs
Change-Id: I3fb4f1d966172bac2f6c52d41c4564f905765212
Abolish cryptfs_revert_ext_volume, handle in caller. This allows us to
use DeleteDeviceIfExists, avoiding a spurious error message.
Test: create private volume on Cuttlefish, eject, check logs
Bug: 147814592
Change-Id: I836d8bd11b29e32da0863aaa75144543bb9cab9c
Not for security, but for consistency with the way we handle other
keys, and to move the length check to where it belongs.
Test: create private volume on Cuttlefish
Bug: 147814592
Change-Id: I10fc4896183d050ce25ff174faf78f525cf62930
Move most of it into cryptfs.cpp, and include cryptfs.h in fewer files.
Bug: 147814592
Test: Treehugger
Change-Id: Ia3592d73e7abc1f07a60538e0978a3033bdea7de
This mostly 1:1 replaces manual ioctls to device-mapper with calls to
libdm. There were two exceptions:
(1) There is a very old table-load-retry loop to workaround issues with
umount (b/7220345). This loop has been preserved, however, it now
includes DM_DEV_CREATE as well as DM_TABLE_LOAD.
(2) There was some ancient code to set DM_DEV_GEOMETRY for obb
dm-devices. This never did anything since geometry must be set after
loading a table. When setting it before (as vold was doing), the
subsequent DM_TABLE_LOAD will clear it.
Bug: 132206403
Test: FBE device boots
FBE device w/ metadata encryption boots
FDE device boots
atest StorageManagerIntegrationTest
Change-Id: Ib6db6b47329f093ac7084edaf604eddace8b9ac6
This trigger was used on FDE devices to bring down the minimal
framework, and worked by shutting down the 'main' service class.
With APEX being introduced, we want to restart all services that were
started after the tmpfs /data was mounted, as those are the services
that haven't been able to use updated APEXes in the (real) /data.
In order to do this, we need to reset more classes; that in turn
made the 'shutdown_main' trigger pretty much similar to the
previously existing 'trigger_shutdown_framework' trigger; so instead
of keeping two duplicate triggers, use only the
'trigger_shutdown_framework' one.
Bug: 118485723
Test: Taimen configured as FDE boots, Taimen configured as FBE boots
Change-Id: I0d80ef2528bd70870b063a2c580cd00a03de9961
cryptfs.cpp and MetadataCrypt.cpp can use android::vold::sFsckContext directly.
hash.h is unuseful.
Test: make
Change-Id: I7acdac97d6ed1c9b2a5dc367fcea8aa2942192e8
Log the main configuration of the dm-crypt device -- the name, the
cipher, the keysize, the real device, and the length -- in addition to
the extra parameters which we were already logging.
(We can't simply log the actual string passed to the kernel, of course,
because that includes the key. So we choose the fields individually.)
Test: booted device configured to use FDE and checked the log message
Change-Id: Ia95de807c4fad68d93b7e7e73508a01e5139dc76
This is needed to make adoptable storage volumes work with a 4K crypto
sector size when the block device size is not a multiple of 4K.
It is fine to do this because the filesystem ends on a 4K boundary
anyway and doesn't use any partial block at the end.
Bug: 123375298
Test: booted device configured to use FDE with sector size 4k, ran
'sm set-virtual-disk true' and formatted the virtual SD card as
adoptable storage. Then did the same but with a temporary patch
that changed kSizeVirtualDisk to be misaligned
Change-Id: I95ee6d7dcaaa8989c674aea9988c09116e830b0c
When generating the key and salt we weren't checking for an error
opening or reading from /dev/urandom. Switch to the helper function
ReadRandomBytes() and start checking for errors.
Test: Booted device with FDE. As a extra sanity check I also
temporarily added log messages that dump the key and salt,
and I verified they still appear random.
Change-Id: I01ccee4f1f9910bf9508c8f02a918157393b0e68
We do not know what happened if remove dm-crypt device is failed, so
the error status added is useful to debug failed ioctl.
Change-Id: I49be91b9087ef2a213a706dd6b2a07eb6dafe6e6
Signed-off-by: Yue Hu <zbestahu@gmail.com>
We add the property ro.crypto.fde_sector_size to allow devices
to pass the "sector_size:<size>" argument to dm-crypt in the kernel.
We also pass "iv_large_sectors" when setting the sector size.
Using 4096-byte sectors rather than the default of 512 improves
dm-crypt performance, especially when the Adiantum encryption mode
is used.
Bug: 112010205
Test: Run on a device
Change-Id: I144ec7088a0aad3430369dc7158370d7ff3ef5d2
Adiantum is a crypto method Android is supporting for devices
which don't have AES CPU instructions. See the paper
"Adiantum: length-preserving encryption for entry-level processors"
(https://eprint.iacr.org/2018/720.pdf) for more details.
We add Adiantum to our list of supported crypto types.
Bug: 112010205
Test: Tested on a device
Change-Id: Ic190a9b90fc8bc077fdc7d60c9d5ae8d8f555025
persist_get_max_entries() is supposed to return an unsigned integer as the
maximum number of entries but it also wrongly returns "-1" as an error
condition. Also fix an issue where an unsigned subtraction in this routine
could lead to integer underflow.
Bug: 112731440
Test: manual
Change-Id: I9672e39bef2c12156dda7806a08c52044962c178
It can sometimes take a moment for the dm-device to appear after
creation, causing operations on it such as formatting to fail.
Ensure the device exists before create_crypto_blk_dev returns.
Test: adb sm set-virtual-disk true and format as adoptable.
Bug: 117586466
Change-Id: Id8f571b551f50fc759e78d917e4ac3080e926722
Merged-In: Id8f571b551f50fc759e78d917e4ac3080e926722
We support file-based encryption on both ext4 and f2fs now, and the
kernel API is the same. So rename things appropriately in vold:
e4crypt => fscrypt
ext4enc => fscrypt
Ext4Crypt => FsCrypt
EXT4_* => FS_*
ext4_encryption_key => fscrypt_key
Additionally, the common functions shared by 'vold' and 'init' are now
in libfscrypt rather than ext4_utils. So update vold to link to
libfscrypt and include the renamed headers.
Note: there's a chance of 'fscrypt' being confused with the dm-crypt
based encryption code in vold which is called 'cryptfs'. However,
fscrypt is the name used in the kernel for ext4/f2fs/ubifs encryption,
and it's preferable to use the same name in userspace.
Test: built, booted device with f2fs encryption
Change-Id: I2a46a49f30d9c0b73d6f6fe09e4a4904d4138ff6